我一直认为 TypeScript 不会跟踪对象突变。例如:
type DescribableObject = {
name: string;
age: number;
};
// error
const obj: DescribableObject = {
name: 'sdf'
}
obj.age = 2
Run Code Online (Sandbox Code Playgroud)
但是,似乎在某些情况下它会跟踪函数静态属性的突变。
type DescribableFunction = {
description: string;
(): boolean;
};
// error
const fn: DescribableFunction = () => true
//fn.description = 'hello';
Run Code Online (Sandbox Code Playgroud)
如果取消注释//fn.description = 'hello';,TypeScript 错误将消失。
此外,如果您将鼠标悬停在上面,fn您会看到 TS 将其fn视为某种module.
fn函数是一个什么样的模块?这种行为有记录吗?
从 TypeScript 3.1 开始,您可以在函数上定义“expando”属性。这是在microsoft/TypeScript#26368中实现的,作为对microsoft/TypeScript#15868的修复。显然,开发人员在 JavaScript 中向函数添加属性有一些常见的模式,但在此功能之前,TypeScript 中没有惯用的方法来执行此操作。
现在你可以这样做:
function foo(x: string) { foo.callCount++; return x.length }
foo.callCount = 0;
Run Code Online (Sandbox Code Playgroud)
但在 TypeScript 3.1 之前,你必须这样做:
function bar(x: string) { bar.callCount++; return x.length }
namespace bar {
export var callCount = 0;
}
Run Code Online (Sandbox Code Playgroud)
或这个:
const baz = Object.assign(
(x: string) => { baz.callCount++; return x.length },
{ callCount: 0 }
);
Run Code Online (Sandbox Code Playgroud)
甚至这个:
const qux = ((x: string) => { qux.callCount++; return x.length }) as
{ (x: string): number; callCount: number };
qux.callCount = 0;
Run Code Online (Sandbox Code Playgroud)
所有这些都相当难看。
虽然按照microsoft/TypeScript#12416DescribableObject中的要求允许所有对象(例如 )而不仅仅是函数上扩展属性可能会很好,但这似乎不是一种常见或重要的支持模式。一般来说,您可以使用对象文字一次添加您想要的所有属性(尽管有时依赖关系可能很难处理),但您不能使用函数来做到这一点。