函数最初不允许更改只读属性(例如,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
从name
获得了Function
,但仍然无法通话:
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
来保持writableFoo
可调用并允许name
进行更改,最好不要使用Writable
修改其他属性。它不会尝试解决特定的编码问题,而是研究指定的类型问题。
为什么1不影响交点类型的readonly
修饰符?
为什么2被name
识别为typeof foo
却没有得到foo.name
?
从readonly
删除name
修饰符时,2-4如何获得呼叫签名?
答案 0 :(得分:2)
与此同时,您可以调用和写name
interface Foo extends Function{
name: string
}
const d: Foo = function(){}
d.name ='not foo'
d()
谢谢。它从技术上解决了问题,但Function忽略了 函数的签名d(“应导致TS错误”,“意外 args')(问题中未提及,但似乎是 合理要求)。 const本身也可以消除错误 因为对它的处理方式不同于让我们
type Incrementer = (x: number)=>string
interface Foo extends Incrementer{
name: string
}
let d: Foo = (x)=>'a'+x
d.name ='not foo'
d(1)
d('s') // string not expceted must be number
如果您想要一个一般性的答案,这是您的Writable
interface Writable<T extends (...args: any) => any> {
(...arg: Parameters<T>): ReturnType<T>;
name: string
}
type Incrementer = (x: number, y: boolean) => string
let d: Writable<Incrementer> = (x, y) => 'a' + x + y
d.name = 'not foo' // no error
d(1, true) // no error
d('d', true) // 'd' is not assignable to number
d(2, 1) // 1 is not assignable to boolean