LinkedList与类型别名

问题描述 投票:0回答:2

我走过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>'

我在哪里弄错了?

typescript type-alias
2个回答
1
投票

如果您使用字符串null检查(使用strictstrictNullChecks选项),则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;

2
投票

@ 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元素。

© www.soinside.com 2019 - 2024. All rights reserved.