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

如何使用TypeScript泛型更新接口的可写字符串属性?

解决方案

要实现满足你需求的泛型函数,需要同时完成筛选可写字符串属性、禁止只读属性和类型安全赋值三个目标,以下是具体实现:

类型定义与函数实现

首先定义筛选规则,再实现泛型函数:

// 辅助类型:判断两个类型是否完全相等
type Equal<X, Y> =
  (<T>() => T extends X ? 1 : 2) extends
  (<T>() => T extends Y ? 1 : 2) ? true : false;

// 筛选T中「可写」且「类型为string/可选string」的属性键
type WritableStringKeys<T> = {
  [P in keyof T as T[P] extends string | undefined ? P : never]: T[P]
} extends { [Q in infer K]: infer V }
  ? K extends keyof T
    ? // 对比原属性与移除readonly后的属性,一致则说明非只读
      Equal<T[P], { -readonly [Q in P]: T[P] }[P]> extends true
      ? K
      : never
    : never
  : never;

// 泛型函数实现
function doSomething<T, K extends WritableStringKeys<T>>(t: T, key: K) {
  // 类型断言确保赋值兼容string/可选string类型
  t[key] = "123" as T[K];
}

测试验证

用你提供的Whatever接口测试:

interface Whatever {
  a: string;
  b?: string;
  readonly c: string;
  d: number;
  e?: boolean;
};

const w: Whatever = {
  a: "this",
  b: "is",
  c: "frustrating",
  d: 0
}

doSomething(w, "a"); // ✅ 正常运行(可写string属性)
doSomething(w, "b"); // ✅ 正常运行(可选string属性)
doSomething(w, "c"); // ❌ 编译错误(readonly属性被禁止)
doSomething(w, "d"); // ❌ 编译错误(number类型属性被排除)
doSomething(w, "e"); // ❌ 编译错误(boolean类型属性被排除)
doSomething(w, "f"); // ❌ 编译错误(不存在的属性)

关键逻辑说明

  1. 筛选字符串属性:
    通过映射类型[P in keyof T as T[P] extends string | undefined ? P : never]只保留类型为string或undefined的属性键。

  2. 排除只读属性:
    利用Equal辅助类型对比原属性和移除readonly修饰符后的属性类型,若一致则说明该属性是可写的(只读属性的类型会与移除readonly后的类型存在差异)。

  3. 类型安全赋值:
    泛型K extends WritableStringKeys<T>让TypeScript准确推断T[K]的类型为string | undefined,使用as T[K]确保字符串赋值与目标类型兼容。

简化版本(TypeScript 4.4+)

如果不需要兼容旧版TypeScript,可使用更简洁的写法:

// 直接筛选可写的string/可选string属性
type WritableStringKeys<T> = keyof {
  [P in keyof T as T[P] extends string | undefined ? P : never]-?: T[P]
};

function doSomething<T, K extends WritableStringKeys<T>>(t: T, key: K) {
  t[key] = "123" as T[K];
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 04:35:53