在Typescript中自动初始化字符串文字类型的成员字段

时间:2017-01-09 18:36:10

标签: typescript

如果我有课程

class Foo {
  type: "foo"
  constructor(public id: number) {}
}

class Bar {
  type: "bar"
  constructor(public id: number) {}
}

type SomeUnion = Foo | Bar // (x : SomeUnion).type will have the type "foo" | "bar"

构建new Foo(1)的实例会在运行时产生{ id: 1 },但我希望得到{ id: 1, type: "foo" }

一个简单的解决方案当然是在字符串常量中键入两次,方法是在构造函数中将其赋值为this.type = "class_name"

然而,这是不理想的,因为我需要两次输入相同的字符串常量。这不是什么大不了的事,但这是一种可以忘记并导致错误的事情。

有没有办法自动创建具有与字符串文字相同值的对象成员?

4 个答案:

答案 0 :(得分:3)

我认为这会做你想要做的事情。你仍然需要输出两次字符串文字,但是它们是非常接近的,所以你不太可能忘记类类型是否会更改以更新这两个值。

class Foo {
  type: "foo" = "foo"
  constructor(public id: number) {}
}

class Bar {
  type: "bar" = "bar"
  constructor(public id: number) {}
}

答案 1 :(得分:2)

让我们专注于这段代码:

class Foo {
  type: "foo"
  constructor(public id: number) {}
}

如果编译器选项strictNullChecksfalse,则type: "foo"隐式还允许将type设置为值undefinednull。我希望明确将字段初始化为undefined以外的值是显而易见的。

让我们继续将strictNullChecks设置为true。在这种情况下,可以分配给type的唯一值是"foo"。看起来你希望有一些方法让编译器执行以下推理:

  

type: "foo"表示名为type的字段必须为"foo"类型。因此,只能为其分配值"foo"。因此,我应该发出代码以自动将其初始化为"foo",因为没有其他值可以分配给它。

问题在于,即使分配strictNullChecks无效,TypeScript 2.x即使使用undefined也允许字段以值undefined开头。我明确地说明了这一点:即使你不能将值undefined 分配给type,字段type也可以开始undefined(如果你没有初始化它)。这不算错误。这就是TypeScript目前的设计方式。有一个issue report about this,有些人认为这是该语言的设计缺陷。

无论如何,编译器不会执行上面所需的推理。 目前,无论如何,您必须重复相同的值作为字符串文字类型的一部分,并作为type字段初始化的一部分。

答案 2 :(得分:1)

如果“类型是字符串文字很重要,而不是通用字符串,以便将它用于程序中其他地方的联合类型”那么你应该有一个类型用于该联合,让我们说:

type MyType = "foo" | "bar";

然后:

class Foo {
  type: MyType = "foo";
  constructor(public id: number) {}
}

class Bar {
  type: MyType = "bar";
  constructor(public id: number) {}
}

您还可以拥有一个共同的基类:

class Base
  type: MyType;
  protected constructor(type: MyType) {
    this.type = type;
  }
}

class Foo extends Base {
  constructor(public id: number) {
    super("foo");
  }
}

class Bar extends Base {
  constructor(public id: number) {
    super("bar");
  }
}

答案 3 :(得分:0)

怎么样?

class Foo {
    type: string;
    constructor(public id: number) {
       this.type = "class_name";
    }
}