TypeScript 3.7 推出断言函数 https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions它可以用来缩小传入参数的类型,甚至this
。断言函数看起来有点像用户定义的类型保护 https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards,但是你添加一个asserts
类型谓词之前的修饰符。这是您可以实施的方法Extendable
作为一个班级add()
作为断言方法:
class Extendable {
add<K extends PropertyKey, V>(key: K, val: V): asserts this is Record<K, V> {
(this as unknown as Record<K, V>)[key] = val;
}
}
你打电话时m.add(key, val)
编译器断言m
将有一个属性,其键的类型为key
以及类型对应的值val
。使用方法如下:
const m: Extendable = new Extendable();
// ~~~~~~~~~~~~ <-- important annotation here!
m.add('one', 1)
m.add('two', 2)
console.log(m.one.toFixed(2)); // 1.00
console.log(m.two.toExponential(2)); // 2.00e+0
这一切都按您的预期进行。打电话后m.add('one', 1)
,你可以参考m.one
没有编译器警告。
不幸的是有一个相当重要的警告 https://github.com/microsoft/TypeScript/pull/33622;断言函数仅在具有显式注释类型时才起作用。根据相关拉取请求 https://github.com/microsoft/TypeScript/pull/32695,“这个特定规则的存在使得潜在断言调用的控制流分析不会循环触发进一步的分析。”
这意味着以下内容是错误的:
const oops = new Extendable(); // no annotation
oops.add("a", 123); // error!
//~~~~~~~~ <-- Assertions require every name in the call target to be declared with
// an explicit type annotation.
唯一的区别是类型oops
is inferred to be Extendable
代替带注释的 as Extendable
as m
是。你会收到一个错误调用oops.add()
。根据您的用例,这可能没什么大不了的,也可能是一个大问题。
好的,希望有帮助;祝你好运!
链接到代码 https://www.typescriptlang.org/play/#code/MYGwhgzhAECiAeAXApgOwCZgEYmdA3gFDQnRjroA8A0tMkmujAAoBOA9gA7KuICe1ZHwA00AGoA+ABQBrIQC5o1UQDcwIRWICUiyBB6IYiABYBLGOegAlZMHasqy8RILFS7qScuRoAV1QyqOwA7qhkMDZ2DjSikloA2nJ8ALrQALzQaiAA3G4kAL6EhdCEdqgQiNAAtooIKBjYuOnQqMjBcAwNOMhSWrkA9P3u0AB+Y+MTY9CUALQz0KZVnPaIYKiVa0GriKbsYcY8yACEhFUAdOToUgDke8jXogCMWqcXFDeIwewP0ABML6U9hB2LgziB2ABzKTnO5nRDsABipngyCu-z60EG0EeZwADLjAeUQcgwZDoXCvnD2Ahlq11qZ1FJ0dlMUNfnjccgANQEwkVaDsLgwDKtdp1RiNHoYrFBMioLZgHZ7NyCzgQN5XABEYE1T1+AGZpUMeBxWCdBpNxtM5tAAIJQAy7crQVjIACOvlMrroKh4fBaYCqeFMYRMeGA6hA0FWrAhyEq8OgWDw6Fs4Fd6GgwVMJkIWLWdHgnBApmAOejfG4coVStQZ0IhCAA