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

如何修改TypeScript自定义类型MyType,仅接受基类相关字段名?

解决TypeScript自定义类型筛选特定基类相关字段名的问题

原代码的问题在于,你将不符合条件的字段类型设为never后,MyType<MyClass>最终会变成string | Valid[] | Valid | never——而never在联合类型中会被自动忽略,剩余的string类型会包含所有字符串字面量(比如"name"),导致所有键都能通过校验。

正确的类型定义

我们需要调整MyType,让它只保留那些字段类型是WhateverBaseClass或其子类数组的键名:

class WhateverBaseClass {}

class Invalid {
  public invalidName!: string;
}

class Valid extends WhateverBaseClass {
  public validName!: string;
}

class MyClass {
  public name!: string;              // 不符合:string类型
  public validArray!: Valid[];       // 符合:Valid子类数组
  public validField!: Valid;         // 符合:Valid子类实例
  public invalidField!: Invalid[];   // 不符合:Invalid非子类数组
}

// 修正后的MyType
type MyType<T> = {
  [K in keyof T]: 
    // 判断字段是否是基类实例
    T[K] extends WhateverBaseClass 
      ? K 
      // 判断字段是否是基类子类的数组
      : T[K] extends Array<infer U> 
        ? U extends WhateverBaseClass 
          ? K 
          : never 
        : never;
}[keyof T];

// 验证:仅接受"validArray"和"validField"
const expectation: MyType<MyClass>[] = ["validArray", "validField"]; // 无报错,符合预期

// 以下代码会触发TypeScript错误(符合预期)
// const error: MyType<MyClass>[] = ["validArray", "validField", "name", "invalidField"];

逻辑说明

  1. 遍历T的所有键K,对每个键对应的类型T[K]做两层判断:
    • 第一层:直接判断是否是WhateverBaseClass或其子类的实例;
    • 第二层:如果是数组类型,提取数组元素类型U,判断U是否是WhateverBaseClass或其子类;
  2. 符合条件的键返回自身类型K,不符合的返回never;
  3. 通过[keyof T]提取所有符合条件的键名,never会被自动排除,最终得到的是符合要求的键名联合类型("validArray" | "validField")。

内容的提问来源于stack exchange,提问作者naPham

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 19:03:09