我試圖讓 TS 泛型映射到一個新物件。簡而言之,我正在嘗試轉換:
{
key: { handler: () => string },
key2: { hander: () => number },
}
到:
{ key: string, key2: number }
完整示例:
type programOption = {
validator: () => unknown
}
type programConfig<T extends {[key: string]: programOption} = {}> = {
options: T,
handler: (data: mapProgramConfig<T>) => void,
}
type mapProgramConfig<T extends {[key: string]: programOption}> = {
[K in keyof T]: ReturnType<programOption['validator']>
}
type mapProgramConfigHardcoded<T> = {
fruit: string,
animal: number
}
class Program {
constructor (config: programConfig) {}
}
const foo = new Program({
options: {
'fruit': { validator: () => 'asdf' },
'animal': { validator: () => 42 },
},
handler: ({fruit, animal, thing}) => {
},
});
如果您在型別中替換mapProgramConfig為mapProgramConfigHardcoded,可以看到我正在嘗試做什么programConfig,但我似乎無法使其在通用情況下作業。
ts游樂場鏈接
uj5u.com熱心網友回復:
考慮這個解決方案:
type ProgramOption<T> = {
validator?: () => T
}
type Convert<Obj extends Record<string, ProgramOption<any>>> = {
[Prop in keyof Obj]: Obj[Prop]['validator'] extends () => infer Return ? Return : never
}
const program = <
Keys extends PropertyKey,
ValidatorValues extends string | number,
Options extends Record<Keys, ProgramOption<ValidatorValues>>,
Handler extends (data: Convert<Options>) => void,
>(data: { options: Options, handler: Handler },) => {
return data
}
const foo = program({
options: {
'fruit': { validator: () => 'string' },
'animal': { validator: () => 42 },
},
handler: (obj) => {
obj.animal // 42
obj.fruit // 'string'
}
});
操場
為了推斷屬性中的obj引數,handler您需要推斷所有嵌套的鍵和值。
Keys- 參考fruit和animal嵌套物件的鍵
ValidatorValues- 參考Validator回傳型別
Options- 參考整個options屬性
Handler- 相應地參考handler。
我已經使用Convert實用程式型別來遍歷Options型別并獲取所有回傳型別的validator屬性
如果您對函式引數推理感興趣,可以查看我的文章
我使用program函式而不是Program類,因為
Type parameters cannot appear on a constructor declaration
uj5u.com熱心網友回復:
你可以這樣定義
type programConfig<T extends Record<string, any>> = {
options: {
[K in keyof T]: {
validator: () => T[K]
}
},
handler: (data: T) => void, // ??? should be {optionKey: inferred return type}
}
class Program<T extends Record<string, any> = Record<string, any>> {
constructor(config: programConfig<T>) { }
}
當您呼叫它時,泛型將僅使用必要的資料(鍵和資料型別)進行推斷
const foo: Program<{
fruit: string;
animal: number;
}>
TS游樂場
uj5u.com熱心網友回復:
您只需要將programConfig介面上定義的泛型擴展到Program類:
class Program<T extends {[key: string]: programOption} = {}> {
constructor (config: programConfig<T>) {}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/349969.html
上一篇:我如何處理Jest中的承諾?
