为什么typescript允许用新属性扩展函数

ffvjumwh  于 2023-04-22  发布在  TypeScript
关注(0)|答案(1)|浏览(166)

当typescript自己推断函数类型时(看sampleFunc1),它允许我用new prop扩展它,但是当我显式地设置函数类型或函数从其他函数(sampleFunc2returnedSampleFunc)返回时,这个功能被阻止了。换句话说,对于所有情况,函数类型都应该是() => number,但只有第一个typescript允许扩展它,为什么?

const sampleFunc1 = () => { return 1 }   
const sampleFunc2: () => number = () => { return 1 }
const returnFunc = (func: () => number) => func
const returnedSampleFunc = returnFunc(sampleFunc1)

// sampleFunc1.Test = "test" // it works
// sampleFunc2.Test = "test" // Property 'Test' does not exist on type '() => number'
// returnedSampleFunc.Test = "test" // Property 'Test' does not exist on type '() => number'

在下面的例子中我们可以看到,对于对象类型,扩展是完全不允许的。那么为什么允许它用于函数呢?

const obj1 = {a: 1, b: "test"}
const obj2: {a: number, b: string} = {a: 1, b: "test"}

// obj1.Test = "test" // Property 'Test' does not exist on type '{ a: number; b: string; }'
// obj2.Test = "test" // Property 'Test' does not exist on type '{ a: number; b: string; }'

Playground

xytpbqjk

xytpbqjk1#

Expando properties on functions是在microsoft/TypeScript#26368中实现并随TypeScript 3.1发布的TypeScript的文档功能。引入此功能是为了修复功能请求microsoft/TypeScript#15868,以允许在TypeScript中支持此常见的JavaScript模式。
在此之前,很难向像这样的函数添加对象

function foo() { }
foo.bar = true; // error!

您必须重构以使用namespace

function foo() { }
namespace foo { export let bar = true };

或者你必须使用类似Object.assign()的东西来隐藏额外的属性:

const foo = Object.assign(function foo() { }, { bar: true });

对于将JavaScript迁移到TypeScript的人来说,这两种重构都不是特别符合人体工程学。
对象不支持这一点,因为向initializer添加额外的属性要容易得多:

const foo = {
    baz: "abc",
    bar: true
}

Playground链接到代码

相关问题