在ES6中,函数最初不允许更改只读属性(例如name
):
let foo = function (n: number) {
return n;
}
foo.name = 'not foo'; // Cannot assign to 'name' because it is a read-only property
为了解决这个问题,使用了参考文献中的
Writable
实用程序类型。type Writable<T> = {
-readonly [K in keyof T]: T[K];
};
1. 只读属性name
不受交集影响:
let writableFoo: typeof foo & { name: string } = foo;
writableFoo.name = 'not foo'; // Cannot assign to 'name' because it is a read-only property
2. Writable
无法从函数类型获取 name
,也无法调用:
let writableFoo: Writable<typeof foo> = foo;
writableFoo.name = 'not foo'; // Property 'name' does not exist on type 'Writable<(n: number) => number>'
writableFoo(1); // This expression is not callable
3. Writable
从 Function
中获取 name
,但仍然无法调用:
let writableFoo: Writable<Function> = foo;
writableFoo.name = 'not foo';
writableFoo(1); // This expression is not callable
4. Omit
使用索引签名,并且也不可调用:
let writableFoo: Omit<typeof foo, 'name'> & { name: string } = foo;
writableFoo.name = 'not foo';
writableFoo(1); // This expression is not callable
这里的目标是输入 writableFoo
以保持其可调用性并允许更改name
,最好不要使用其他具有Writable
的属性。它不试图解决特定编码问题,而是研究指定类型问题。
为什么1不会影响交集类型的readonly
修饰符?
为什么2没有获取name
,尽管它在typeof foo
中被识别为foo.name
?
如何使2-4可以获得调用签名并从name
中移除readonly
修饰符?
Object.defineProperty
,因为它是可配置的,你可以通过这种方式覆盖它。 - Icepickletypeof foo & { name: string }
创建的是一个交集,而不是一个联合类型typeof foo | { name: string }
。 - Naresh Pingale