如何解决继承已知接口的泛型类型的只读数组键类型报错问题?
TypeScript泛型接口中只读数组键的类型提示问题
我是TypeScript新手,若问题表述不当请见谅。我有一个接受泛型类型的接口,该泛型继承自已知接口(已知类型为foo,泛型类型为T)。我试图获取关联只读数组的已知必填只读键,该逻辑对foo有效但对泛型T无效。
问题代码
export type KeysOfReadonlyArraysOf<Obj> = { [K in keyof Obj]: Obj[K] extends ReadonlyArray<any> ? K : never }[keyof Obj] export type ReadonlyArrayValuesOf<T, V extends KeysOfReadonlyArraysOf<T>> = T[V] extends Readonly<any[]> ? T[V][number] : never; interface foo { bar: ReadonlyArray<string>, baz: number } interface itest2<T extends foo>{ field: ReadonlyArrayValuesOf<T,"bar"> }
其中"bar"标红且无智能提示。
我的tsconfig配置
{ "compilerOptions": { "target": "ESNext", "useDefineForClassFields": true, "module": "ESNext", "lib": ["ESNext", "DOM"], "moduleResolution": "Node", "strict": true, "alwaysStrict": true, "resolveJsonModule": true, "isolatedModules": true, "esModuleInterop": true, "noEmit": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "skipLibCheck": true }, "include": ["src","__tests__"] }
解决方案
问题核心:当T是泛型(T extends foo)时,TypeScript无法提前确定T的bar属性一定是ReadonlyArray类型(因为T可能覆盖该属性),所以无法将"bar"识别为KeysOfReadonlyArraysOf<T>的合法值。
方案1:约束泛型的只读数组键
调整itest2的泛型约束,确保T的bar属性始终是只读数组类型:
interface itest2<T extends foo & { bar: ReadonlyArray<any> }> { field: ReadonlyArrayValuesOf<T, "bar"> }
方案2:基于基础接口推导合法键
既然T继承自foo,直接基于foo推导合法键,而非依赖泛型T:
// 修改类型工具,基于foo推导键 export type ReadonlyArrayValuesOf<T, V extends KeysOfReadonlyArraysOf<foo>> = T[V] extends Readonly<any[]> ? T[V][number] : never; interface itest2<T extends foo> { field: ReadonlyArrayValuesOf<T, "bar"> }
如果需要更灵活的复用,可增加基础类型参数:
export type ReadonlyArrayValuesOf<T extends Base, V extends KeysOfReadonlyArraysOf<Base>, Base> = T[V] extends Readonly<any[]> ? T[V][number] : never; interface itest2<T extends foo> { field: ReadonlyArrayValuesOf<T, "bar", foo> }
方案3:放宽键约束并通过条件类型过滤
直接让V为T的键,再通过条件类型判断是否为只读数组,同时保留智能提示:
export type ReadonlyArrayValuesOf<T, V extends keyof T> = T[V] extends Readonly<any[]> ? T[V][number] : never; interface itest2<T extends foo> { field: ReadonlyArrayValuesOf<T, "bar"> }
内容的提问来源于stack exchange,提问作者A Kam
相关产品推荐
相关产品推荐

