【发布时间】:2019-12-30 05:54:28
【问题描述】:
我正在使用 TypeScript 编写一个类型化的 List 实现,作为一个普通对象,其结构使用 type 表达式来确保。我选择把它写成一个普通对象而不是一个类,因为我相信一个普通对象更容易让我确保它的不变性。该对象的类型定义如下:
type List<T> = Readonly<{
head: T;
tail: List<T> | void;
}>;
我想为这个结构编写一个类型保护,这样我就可以在其他代码中确保我正在对List 对象进行操作。我当前的类型保护如下所示:
export function isList(list: any): list is List {
if (isNil(list)) {
return false;
}
return ("head" in list && "tail" in list);
}
这个实现在第一行有一个错误,在 list is List:TypeScript 抱怨类型 List<T> 是通用的,因此,我必须在引用中提供一个类型。
此函数的预期输出如下:
import {getListSomehow, isList} from "list";
const list = getListSomehow("hello", "world", "etc...");
const arr = ["hello", "world", "etc..."];
console.log(isList(list)); // true
console.log(isList(arr)); // false
console.log(isList("a value")); // false
有没有什么方法可以不用知道T 的类型就可以写出这种类型保护?如果没有,有没有办法以某种方式检索这种类型,同时仍然允许函数获取任何值?
【问题讨论】:
-
你试过
list is List<any>吗? -
我应该指出,您可能以错误的方式处理此问题。与其让
isList检查list是否看起来像一个列表并且嘎嘎叫像一个列表,不如只检查变量是否是List<T>并完全避免使用未知类型的变量(@ 987654333@). -
@Zenexer - Facepalms. 我不敢相信我错过了。我在
list类型定义中使用它,所以我不知道为什么我没有考虑在List<T>中使用它。另外,我如何直接检查它是否是List<T>? -
将 TypeScript 用于其预期目的:如果变量声明为
List<T>类型,则它是List<T>。首先你不需要测试,因为如果你的代码不是List<T>,但你像使用它一样使用它,你的代码将无法编译——除非你使用any,这打破了TypeScript的保证。就目前而言,我可以创建一个通过isList但实际上不是List<T>的对象:{head: 1, tail: {head: "a"}} -
好的。谢谢。
标签: typescript typescript-generics typeguards