如何描述该函数通过引用使对象变异?

时间:2019-11-07 03:38:37

标签: typescript

我有一个通过引用修改对象的函数:

function addProp(object, value) {
  object.foo = value;
}

如何在调用object函数之后告诉TypeScript addProp值更改其类型?我期望这样的代码:

interface WithProp<T> {
  foo: T;
}

function addProp<T1 extends object, T2>(object: T1 mutatesTo (T1 & WithProp<T2>), value: T2) {
  object.foo = value;
}

const obj = { bar: 'baz' };
obj.foo; // TS: error
addProp(obj, 123);
obj.foo; // TS: ok

1 个答案:

答案 0 :(得分:2)

类型系统并不是真正适合于变量类型的变异。它至少在某些代码块中使用control flow analysis来缩小变量的类型,但是直到最近,还没有办法编写addProp()来触发这种基于控制流的缩小

TypeScript 3.7引入了assertion functions来表示不返回值但可以防止无效状态的函数。它们非常新,并且有一些weird restrictions,因此请注意。

但是您现在可以做的是将addProp()表示为一个断言函数,该函数表明类型T1的输入现在断言为较窄的类型T1 & WithProp<T2>。在这种情况下,如果输入不是该类型,则函数实现不会添加错误,而是通过添加属性来使变为该类型。但是类型系统都是一样的。无论如何,它看起来像这样:

function addProp<T1 extends object, T2>(
    o: T1,
    value: T2
): asserts o is T1 & WithProp<T2> {
    (o as T1 & WithProp<T2>).foo = value;
}

然后按照您想要的方式运行:

let obj = { bar: 'baz' };
obj.foo; // error! foo does not exist on {bar: string}
addProp(obj, 123);
obj.foo; // okay

请注意,这种缩小是控制流分析的结果,该控制流在分配时会重置,因此您可能会对以下操作不起作用感到惊讶(请注意,我在上面放置了let而不是const ):

// weirdness on reassignment
obj = { bar: "baz", foo: 1 }; // error! foo is extra

但这是我能最接近地代表类型系统中的此类突变的信息。好吧,希望这会有所帮助;祝你好运!

Link to code