Abs*_*thm 5 typescript typescript-generics
我正在尝试使用 TS 实现以下目标:
let m: Extendable
m.add('one', 1)
// m now has '.one' field
m.add('two', 2)
// 'm' now has '.one' and '.two' fields
Run Code Online (Sandbox Code Playgroud)
我熟悉通过以下方式在 TS 中返回扩展类型:
function extend<T, V>(obj: T, val: V): T & {extra: V} {
return {
...obj,
extra: val
}
}
Run Code Online (Sandbox Code Playgroud)
现在,在我的情况下有两个问题:
1) 对象m在add()被调用后需要更新其类型以反映新字段的添加
2)新字段的名称被参数化(并不总是extra例如)
第一个问题可能会通过使用类定义并以某种方式使用TypeThis实用程序来重新调整类型来解决,但我无法找到足够的关于如何使用它的文档。
欢迎任何帮助或指导。谢谢!
TypeScript 3.7 引入了断言函数,可用于缩小传入参数的类型,甚至this. 断言函数看起来有点像用户定义的类型保护,但是你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;
}
}
Run Code Online (Sandbox Code Playgroud)
当您调用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
Run Code Online (Sandbox Code Playgroud)
这一切都如您所愿。调用后m.add('one', 1),您可以在m.one没有编译器警告的情况下进行引用。
不幸的是,有一个相当重要的警告;断言函数仅在具有明确注释的类型时才有效。根据相关拉取请求,“存在此特定规则,因此潜在断言调用的控制流分析不会循环触发进一步分析。”
这意味着以下是一个错误:
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.
Run Code Online (Sandbox Code Playgroud)
唯一的区别是,类型oops被推断为Extendable代替的注释作为Extendable为m是。并且您在调用oops.add(). 根据您的用例,这可能没什么大不了的,也可能是一个大问题。
好的,希望有帮助;祝你好运!