[英]Typescript type inference from object
我正在嘗試讓 TypeScript 正確推斷以下代碼示例中的輸入:
type User = {
name: string
}
type Product = {
price: number
}
const userConfig = {
action: () => [{name: 'John'}] as User[],
}
const productConfig = {
action: () => [{price: 123}] as Product[],
}
const entityConfig = {
userConfig,
productConfig,
}
export const makeApp = <K extends string, R>({
config,
}: {
config: Record<K, {action: () => R}>
}) => {
const actions: Record<K, {action: () => R}> = Object.keys(config).reduce(
(acc, curr) => {
const c: {action: () => R} = config[curr as K]
return {
...acc,
[curr]: c.action(),
}
},
{} as any,
)
return {actions}
}
const app = makeApp({config: entityConfig})
const users = app.actions.userConfig.action() // Correctly typed as User[]
const products = app.actions.productConfig.action() // Incorrectly typed as User[] instead of Product[]
我在const app = makeApp({config: entityConfig})
行看到以下 TypeScript 錯誤
Type '{ userConfig: { action: () => User[]; }; productConfig: { action: () => Product[]; }; }' is not assignable to type 'Record<"userConfig" | "productConfig", { action: () => User[]; }>'.
The types returned by 'productConfig.action()' are incompatible between these types.
Type 'Product[]' is not assignable to type 'User[]'.
Property 'name' is missing in type 'Product' but required in type 'User'.ts(2322)
如何將app.actions.userConfig.action()
和app.actions.productConfig.action()
調用的返回類型分別正確推斷為User[]
和Product[]
?
您應該推斷傳入的密鑰 object 並通過{ [key in keyof T ]: T[key] }}
構造一個新接口:
const makeApp = <T, K extends keyof T>({ config }: { config: T }): { actions: { [key in keyof T ]: T[key] } } => {
const actions: { [key in keyof T ]: T[key] } = Object.keys(config).reduce(
(acc, curr) => {
const c = config[curr as K] as unknown as { action: () => void };
return {
...acc,
[curr]: { action: c.action },
}
},
{} as any,
)
return { actions };
}
因為 reducer 不知道傳入的 object 屬性包含action
鍵,所以可以使用config[curr as K] as unknown as { action: () => void };
.
游樂場鏈接。
我不確定你問的問題是否正確,或者我誤解了它。 您已要求從{ config: entityConfig }
形式的 object 開始,並為某些 function makeApp 執行const app = makeApp({config: entityConfig})
。 然后您希望const products = app.actions.productConfig.action()
工作並正確輸入。
然而,這是相當微不足道的,因為 entityConfig 已經是正確的形式,所以我們需要做的就是交換我們的密鑰。 它不需要減少 function。下面的 function 有效:
const makeApp = <T>({ config }: { config: T }): { actions: T }
=> ({ actions: config })
完整代碼:
type User = {
name: string
}
type Product = {
price: number
}
const userConfig = {
action: () => [{name: 'John'}] as User[],
}
const productConfig = {
action: () => [{price: 123}] as Product[],
}
const entityConfig = {
userConfig,
productConfig,
}
const makeApp = <T>({ config }: { config: T }): { actions: T }
=> ({ actions: config })
const app = makeApp({config: entityConfig})
const users = app.actions.userConfig.action() // Correctly typed as User[]
const products = app.actions.productConfig.action() // Correctly typed as Product[]
console.log(users[0].name) // John
console.log(products[0].price) // 123
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.