如何移除TypeScript类型中的所有getter字段?
如何移除TypeScript类型中的所有getter字段?
嘿,这个需求我太熟了!我之前在写DOM属性赋值的工具函数时也碰到过一模一样的问题——就是想把类型里那些只读的getter给去掉,只留下能赋值的部分,不然创建对象或者传参的时候总是报类型不匹配的错。就像你给出的这个例子:
// Assume this type is external interface Foo { get bar(): string; set bar(value: boolean); }; const foo: Foo = { bar: true }; // ERROR: Type 'boolean' is not assignable to type 'string'.
这里TypeScript因为bar有getter返回string,就要求你赋值的bar必须是string,但你实际想对应setter的boolean类型对吧?
那咱们可以用TypeScript的映射类型和条件类型来实现一个工具类型,专门处理这种情况——移除所有纯getter字段,同时把既有get又有set的字段类型替换成setter的参数类型:
type RemoveGetters<T> = { [K in keyof T as T[K] extends { get: () => any } ? (T[K] extends { set: (value: infer V) => void } ? K : never) : K]: T[K] extends { set: (value: infer V) => void } ? V : T[K]; };
我给你拆解下这个工具类型的逻辑:
- 先遍历目标类型
T的每一个属性键K - 第一步判断当前属性是不是带有getter:
T[K] extends { get: () => any }- 如果是带getter的属性,再检查它有没有对应的setter:
- 要是有setter,就保留这个属性键
K,并且把属性类型设为setter接收的参数类型V - 要是没有setter(纯getter的只读属性),直接把这个键排除掉(用
never来过滤)
- 要是有setter,就保留这个属性键
- 如果这个属性本身就没有getter,那就直接保留原有的键和类型
- 如果是带getter的属性,再检查它有没有对应的setter:
现在用这个工具类型转换你的Foo接口试试:
type MutableFoo = RemoveGetters<Foo>; // 此时 MutableFoo 的类型等价于 { bar: boolean; }
再创建对象就完全不会报错了:
const foo: MutableFoo = { bar: true }; // 完美通过类型检查!
放到你提到的applyAttribs函数里也刚好适配:
function applyAttribs<TElem extends Element>(elem: TElem, attribs: RemoveGetters<TElem>) { // 这里可以安全地把attribs的所有属性赋值给elem Object.assign(elem, attribs); }
这样attribs的类型就只会包含TElem中可赋值的属性,那些只读的getter字段会被自动排除,完全符合你想要的场景~
内容来源于stack exchange
相关产品推荐
相关产品推荐

