我有一个通过引用修改对象的函数:
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
答案 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
但这是我能最接近地代表类型系统中的此类突变的信息。好吧,希望这会有所帮助;祝你好运!