You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决继承已知接口的泛型类型的只读数组键类型报错问题?

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 23:15:43