Fla*_*rax 7 typescript typescript-generics
我正在尝试为原始类型创建包装器,如果指定的话,可能具有可为空的值。但遇到了一个问题:TS自动将类型缩小为提供的值。它可以通过泛型中的手动类型规范来绕过,但对于主要用例来说它看起来有点丑陋。
class Wrapper<T> {
constructor(
public value: T
) { }
}
class StringWrapper<T extends string | null = string> extends Wrapper<T> {
}
new Wrapper(`a`); // Wrapper<string> - Perfect
new StringWrapper(`a`); // StringWrapper<'a'> - Too narrowed
new StringWrapper<string>(`a`); // StringWrapper<string> - Ugly
Run Code Online (Sandbox Code Playgroud)
是否有可能避免缩小到字面意思并使这种情况成为可能?
type TClock = `Tic` | `Tac`;
new StringWrapper(1); // TS error
new StringWrapper(`a`); // StringWrapper<string>
new StringWrapper<TClock>(`Tic`); // StringWrapper<TClock>
new StringWrapper<TClock | null>(null); // StringWrapper<TClock | null>
Run Code Online (Sandbox Code Playgroud)
包含, like 的通用约束向编译器提示,如果可能的话,它应该推断出字符串文字类型。这是预期的行为,如microsoft/TypeScript#10676中实现和描述的那样。stringT extends string | nullT
因此,如果您想避免这种缩小,则不能限制T为string | null。一种替代方法是根本不进行约束T,但在任何使用 type 值的地方,都使用交集T值。因此,不可分配给的任何部分都将被删除(例如,减少为)。这与约束具有大致相同的效果,但没有推理行为: T & (string | null)Tstring | null(number) & (string | null)never
class StringWrapper<T,> extends Wrapper<T & (string | null)> { }
Run Code Online (Sandbox Code Playgroud)
所以现在一切都按照你想要的方式进行推理:
type TClock = `Tic` | `Tac`;
new StringWrapper(`a`); // StringWrapper<string>
new StringWrapper<TClock>(`Tic`); // StringWrapper<TClock>
new StringWrapper<TClock | null>(null); // StringWrapper<TClock | null>
Run Code Online (Sandbox Code Playgroud)
但编译器仍然拒绝构造函数参数,这违反了您的预期约束:
new StringWrapper(3) // error
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
71 次 |
| 最近记录: |