我正在使用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']})
答案 0 :(得分:1)
最简单的方法是将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"
。这样一来,您的课堂就能按需工作:
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">
。它们通常是可互换的,但是当只希望为构造函数使用整个类的泛型类型时,似乎不是最佳选择。
但是可以。
好的,希望其中一个想法有所帮助。祝你好运!