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

如何在TypeScript中获取setter属性类型并解决封装参数匹配问题

获取TypeScript对象类型中Setter的属性类型

先看这个场景:定义一个getter和setter类型不同的对象类型:

type Foo = {
    get bar(): number;
    set bar(value: number | string);
}

当用索引访问获取属性类型时,只能拿到getter的类型:

type Bar = Foo["bar"]; // 类型为number

现在需要获取setter的类型(也就是示例里的number | string),试了下面的泛型但没效果:

type SetterType<T, U extends string> = T extends { set [key in U]: infer P } ? P : never;
type Bar = SetterType<Foo, "bar">;

应用场景

现有这样的API:

const foo = addFoo(); // addFoo函数返回Foo类型
foo.bar = 123;
foo.bar = "123"; // setter能正常接收string类型
foo.baz = true;
// 其他属性...

想封装这个函数,通过传入字面量对象设置属性,内部用Object.assign实现:

function myAddFoo(properties: Partial<Foo>): Foo {
    const foo = addFoo();
    Object.assign(foo, properties);
    return foo;
}

const foo = myAddFoo({
    bar: "123", // 报错:`bar`必须是number | undefined
    baz: true,
    // 其他属性...
});

这里的问题是字面量里的bar没法用setter支持的number | string类型,所以得让函数参数兼容setter类型,也就是要推断出所有setter的类型(比如{ bar: number | string }),再调整参数类型:

type FooSetters = /* 推断所有setter类型,如`{ bar: number | string }` */;
function myAddFoo(properties: Partial<Omit<Foo, keyof FooSetters> & FooSetters>): Foo

解决方案

1. 提取单个属性的Setter类型

修改泛型,直接匹配属性的setter签名:

type SetterType<T, K extends keyof T> = T[K] extends { set: (value: infer P) => void } ? P : never;

// 测试
type BarSetter = SetterType<Foo, "bar">; // number | string

2. 提取对象所有属性的Setter类型

如果要一次性提取所有带setter的属性类型,可以用映射类型:

type ExtractSetters<T> = {
    [K in keyof T as T[K] extends { set: any } ? K : never]: 
        T[K] extends { set: (value: infer P) => void } ? P : never
};

// 测试
type FooSetters = ExtractSetters<Foo>; // { bar: number | string }

3. 修正封装函数的参数类型

用上面的ExtractSetters调整myAddFoo的参数类型,让它同时兼容getter和setter的类型:

type ExtractSetters<T> = {
    [K in keyof T as T[K] extends { set: any } ? K : never]: 
        T[K] extends { set: (value: infer P) => void } ? P : never
};

type FooSetters = ExtractSetters<Foo>;

function myAddFoo(properties: Partial<Omit<Foo, keyof FooSetters> & FooSetters>): Foo {
    const foo = addFoo();
    Object.assign(foo, properties);
    return foo;
}

// 现在可以正常传入string类型的bar了
const foo = myAddFoo({
    bar: "123", // 不再报错
    baz: true,
});

原理说明

在TypeScript类型系统中,带getter和setter的属性会被识别为包含get和set方法的对象类型。通过条件类型的infer关键字,可以从setter的函数签名里提取出参数类型,也就是setter接受的值类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 19:40:32