在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"

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

有没有一种方法可以自动创建具有与字符串文字相同值的对象的成员?

让我们专注于这个代码:

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

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


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

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

问题是,即使分配undefined无效,TypeScript 2.x(即使有strictNullChecks)当前也允许字段以值undefined开头。让我明确地说:即使您不能将值undefined分配给type,字段type也可以以值undefined开始(如果您不初始化它)。这不被视为错误。TypeScript就是这样设计的。有一份关于这一点的问题报告,一些人认为这是语言中的设计缺陷。

无论如何,编译器不会执行上述所需的推理目前,您将不得不以某种方式重复相同的值作为字符串文字类型的一部分,并作为type字段初始化的一部分

我认为这将达到您想要的效果。您仍然需要键入两次字符串文字,但它们是在很近的地方键入的,因此您不太可能忘记是否更改了类类型来更新这两个值。

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

如果"重要的是,该类型是字符串文字,而不是通用字符串,以便将其用于程序中其他地方的并集类型",那么您应该有一个用于该并集的类型,比如:

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");
}
}

怎么样?

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

最新更新