删除可调用签名的只读修饰符

时间:2020-08-29 10:56:06

标签: typescript

函数最初不允许更改只读属性(例如,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。 Writablename获得了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如何获得呼叫签名?

1 个答案:

答案 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