具有别名的LinkedList

时间:2018-07-10 12:33:30

标签: typescript type-alias

我经历了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>'

我在哪里弄错了?

2 个答案:

答案 0 :(得分: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元素。

答案 1 :(得分:1)

如果您正在使用字符串空检查(通过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;

问题是现在下一个字段是可选的,因此我们必须在每次访问时检查它是否不为空,或者像我上面所做的那样,使用不为空的断言运算符(!

修改

如果希望将people精确键入对象文字的结构,但要检查对象文字是否符合LinkedList<Person>,则可以使用额外的函数来创建将推断类型的对象对象文字的大小,但如果不符合LinkedList<Person>,则会引发错误。好处是我们不需要任何非null的断言(!),在这种情况下,最大的缺点是列表的长度是固定的,因此不是很有用,但是有趣的是:)

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;