我正在使用 TypeScript 为 Angular 中的模型定义构造函数。模型中的一个属性被设置为具有一些可能的字符串值的枚举。如果我将一个枚举值传递给构造函数,这就可以正常工作。 问题是我需要根据 API 响应调用构造函数,该 API 响应返回需要映射到该属性的值的字符串。
有没有办法将字符串(只要它是枚举中定义的值之一)传递给构造函数?
枚举:
export enum TestTypes {
FIRST = 'first',
SECOND = 'second',
}
export class Test {
this.myType: TestTypes;
constructor(options: {type: TestTypes}) {
this.myType = options.type;
}
}
以下作品
const a = new Test({type:TestTypes.FIRST});
我想实现的目标:
const b = new Test({type:'first'})
我应该执行以下操作吗?
const b = new Test({type:TestTypes['first']})
最佳答案
最简单的方法是将您的 enum
更改为像这样的直接字典:
const literal = <L extends string | number | boolean>(l: L) => l;
export const TestTypes = {
FIRST: literal('first'),
SECOND: literal('second'),
};
export type TestTypes = (typeof TestTypes)[keyof typeof TestTypes]
literal()
函数是一个帮助程序,它提示编译器解释值 as a string literal 而不是扩大到 string
。
现在,值 TestTypes.FIRST
就是字符串 "first"
,值 TestTypes.SECOND
就是字符串 "second"
,类型 TestTypes
就是联合 "first"|"second"
。这可以让您的类(class)按预期工作:
export class Test {
myType: TestTypes; // this is an annotation, not an initializer, right?
constructor(options: { type: TestTypes }) {
// options.type, not type
this.myType = options.type;
}
}
const a = new Test({ type: TestTypes.FIRST }); // okay
const b = new Test({ type: "first" }); // okay... it's the same thing
如果你想将 TestTypes
保留为 enum
,你可以得到你想要的,但在我看来这太过分了。
首先,如果您想要一个接受 enum
或正确的 string
值的独立函数,您可以像这样创建一个 generic function:
declare function acceptTestTypesOrString<E extends string>(
k: E & (Extract<TestTypes, E> extends never ? never : E)
): void;
我不知道是否应该对此进行解释,但它利用了 TestTypes.FIRST extends "first"
等事实。让我们看看它是否有效:
acceptTestTypesOrString(TestTypes.FIRST) // okay
acceptTestTypesOrString(TestTypes.SECOND) // okay
acceptTestTypesOrString("first") // okay
acceptTestTypesOrString("second") // okay
acceptTestTypesOrString("third") // error
看起来不错。但是您希望将其作为构造函数。而你 can't make a constructor function generic 。相反,您可以使整个类通用,如下所示:
export class Test<E extends string> {
myType: E; // this is an annotation, not an initializer, right?
constructor(options: {
type: E & (Extract<TestTypes, E> extends never ? never : E)
}) {
// options.type, not type
this.myType = options.type;
}
}
const a = new Test({ type: TestTypes.FIRST }); // okay
const b = new Test({ type: "first" }); // also okay
在这种情况下,a
将是 Test<TestTypes.FIRST>
类型,而 b
将是 Test<"first">
类型。它们大部分是可以互换的,但是当您只希望构造函数使用通用类型时,为整个类拖拽通用类型似乎不是最佳选择。
但它有效。
好的,希望其中一个想法对您有所帮助。祝你好运!
关于angular - typescript 构造函数 : accept string for enum,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51433319/