【问题标题】:LinkedList with type alias具有类型别名的 LinkedList
【发布时间】:2018-07-10 12:33:30
【问题描述】:

我浏览了TS handbook,来到了我认为非常有吸引力的类型别名概念。然后我尝试运行这段代码sn-p:

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&lt;Person&gt;'.

我在哪里做错了?

【问题讨论】:

    标签: typescript type-alias


    【解决方案1】:

    @TitianCernicovaDragomir 的回答是正确的;通常你会想要某种基本情况,这样你的链表就可以有一个有限的长度。但是,在不太可能的情况下,您想要制作符合原始 LinkedList&lt;Person&gt; 定义的类型安全的东西,您可以执行以下操作:

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

    【讨论】:

      【解决方案2】:

      如果您使用字符串空检查(使用strictstrictNullChecks 选项),则undefined 不能分配给LinkedList&lt;T&gt;

      最简单的选择是将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&lt;Person&gt;,您可以使用额外的函数来创建将推断对象字面量类型的对象但如果不符合LinkedList&lt;Person&gt; 则会引发错误。优点是我们不需要任何非空断言(!),在这种情况下,最大的缺点是列表的长度变得固定,所以不是非常有用,但一个有趣的旁注:)

      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;
      

      【讨论】:

      • Titian,是的,我使用 strictNullChecks 来查看它是否有帮助或让生活更麻烦。
      • @MaciekLeks 我希望两者都有 ;)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多