我走过TS handbook,来到了我认为非常有吸引力的类型别名概念。然后我尝试运行此代码段:
type LinkedList<T> = T & { next: LinkedList<T> };
interface Person {
name: string;
}
var people: LinkedList<Person>;
var s = people.name;
var s = people.next.name;
var s = people.next.next.name;
var s = people.next.next.next.name;
给出了什么(TS v2.9.1):error TS2454: Variable 'people' is used before being assigned.
所以我已经将people
初始化如下:
var people: LinkedList<Person> =
{name: "John", next: {name: "Jannet", next: {name: "Joanna", next: {name: "Adam", next: undefined}}}};
var s = people.name;
var s = people.next.name;
var s = people.next.next.name;
var s = people.next.next.next.name;
但现在我得到了TSError:error TS2322: Type '{ name: string; next: { name: string; next: { name: string; next: { name: string; next: undefined...' is not assignable to type 'LinkedList<Person>'
。
我在哪里弄错了?
如果您使用字符串null检查(使用strict
或strictNullChecks
选项),则undefined
不能分配给LinkedList<T>
。
最简单的选择是使next
字段可选
type LinkedList<T> = T & { next?: LinkedList<T> };
interface Person {
name: string;
}
var people: LinkedList<Person> =
{ name: "John", next: { name: "Jannet", next: { name: "Joanna", next: { name: "Adam", next: undefined } } } };
var s = people.name;
var s = people.next!.name;
var s = people.next!.next!.name;
var s = people.next!.next!.next!.name;
问题是现在下一个字段是可选的,因此我们必须检查每个访问它不是null或使用非null断言操作符,如上所述(!
)
编辑
如果您希望people
完全键入对象文字的结构,但检查对象文字是否符合LinkedList<Person>
,您可以使用额外的函数来创建将推断对象文字类型的对象,但如果它会引发错误不符合LinkedList<Person>
。优点是我们不需要任何非空断言(!
)在这种情况下的最大缺点是列表的长度变得固定,因此不是非常有用,但是有趣的侧面说明:)
function createLinkedList<T extends LinkedList<Person>>(p: T) {
return p;
}
var people = createLinkedList({ name: "John", next: { name: "Jannet", next: { name: "Joanna", next: { name: "Adam" } } } });
var s = people.name;
var s = people.next.name;
var s = people.next.next.name;
var s = people.next.next.next.name;
@ TitianCernicovaDragomir的回答是正确的;通常你需要某种基本情况,这样你的链表就可以有一个有限的长度。但是,在不太可能的情况下,您希望制作符合原始LinkedList<Person>
定义的类型安全的东西,您可以执行以下操作:
class Ouroboros {
name = "AlphaAndOmega";
next = this; // 🔁
}
const people: LinkedList<Person> = new Ouroboros();
console.log(people.name); // "AlphaAndOmega"
console.log(people.next.name); // "AlphaAndOmega"
console.log(people.next.next.name); // "AlphaAndOmega"
console.log(people.next.next.next.name); // "AlphaAndOmega"
在这种情况下,people
是一个circular linked list,只有一个独特的Person
元素。