我在用图书馆https://github.com/ivanhofer/typesafe-i18n
这个库生成强类型的翻译信息和函数,如下所示.(以下是简化的例子)
export type MyTranslations = {
Hello: (arg: { field: unknown}) => string
Bye: (arg: { field: unknown, date: unknown}) => string
Foo: (arg: { field: unknown}) => unknown
Bar: (arg: { max: unknown}) => unknown,
test: string // this is just here to show that not every property of MyTranslations needs to be a function
}
const translations: MyTranslations = {
Hello: (arg: { field: unknown}) => 'hello',
Bye: (arg: { field: unknown, date: unknown}) => 'bye',
Foo: (arg: { field: unknown}) => 'foo',
Bar: (arg: { max: unknown}) => 'bar',
test: '' // this is just here to show that not every property of MyTranslations needs to be a function
}
Now in my code I have a function which should translate messages dynamically, it does not know exactly what I has to translate.
Through TS typing information it knows what I might translate (with keyof
).
Here is the code so far.
I spend already quite some time and I'm not sure if it is even possible or sensible, but I just want to know :)
// preparation
interface MyParams {
[index: string]: boolean | number | string | undefined
field?: keyof MyTranslations
}
interface Result {
transKey: keyof MyTranslations,
params?: MyParams
}
const results: Result[] = [
{
transKey: 'Hello',
params: {
field: 'Bye'
}
},
{
transKey: 'Bar',
params: {
max: 'test'
}
}
]
type PickByType<T, V> = {
[P in keyof T as T[P] extends V | undefined ? P : never]: T[P]
}
翻译功能
function translate(results: Result[]) {
results.forEach((result: Result) => {
type A = PickByType<MyTranslations, Function>
type C = keyof A
if(result.params) {
type T = typeof result.params
type Req = Required<T>
const req = result.params as Req
const func = translations[result.transKey]
type F = typeof func
const f = translations as A
f[result.transKey as C](req)
}
})
}
translate(results)
问题在这里f[result.transKey as C](req)
Error
Argument of type 'Required<MyParams>' is not assignable to parameter of type '{ field: unknown; } & { field: unknown; date: unknown; } & { field: unknown; } & { max: unknown; }'.
Property 'date' is missing in type 'Required<MyParams>' but required in type '{ field: unknown; date: unknown; }'
Which makes sense. Typescript expects an intersection type.
So I thought maybe I can create this type somehow (holding all the required parameters field, max and date
and then, according to this type information create a new object of this new type holding this information, like so in pseudo code
type D = getAllParametersFromTypeAsIntersectionType() // <- this is easy
const newParams = createNewParamsAsTypeD(result.params)
有什么 idea 吗?