Typescript 类型脚本映射枚举

Typescript 类型脚本映射枚举,typescript,Typescript,在我的应用程序中,我们混合使用模拟和真实的REST数据。在TypeScript中,为了方便起见,我定义了一大堆枚举 当我使用数据创建任何类型的模拟数组时,我使用以下压缩: enum MyEnum { 'myEnumValue1' = 0, myEnumValue2 } (...) enumField: MyEnum.myEnumValue1, (...) TypeScript有效地将其解析为数字: (...) enumField: 1, (...) 然而,从RESTAPI中,我收到的枚举

在我的应用程序中,我们混合使用模拟和真实的REST数据。在TypeScript中,为了方便起见,我定义了一大堆枚举

当我使用数据创建任何类型的模拟数组时,我使用以下压缩:

enum MyEnum { 'myEnumValue1' = 0, myEnumValue2 } 
(...)
 enumField: MyEnum.myEnumValue1,
(...)
TypeScript有效地将其解析为数字:

(...)
enumField: 1,
(...)
然而,从RESTAPI中,我收到的枚举集与其字符串表示形式相同。可通过以下方式进行两种转换:

MyEnum['string'] => number
MyEnum[number] => string

MyEnum['myEnumValue1'] => 0
MyEnum[0] => 'myEnumValue1'

是否可以生成以优雅方式处理此转换的泛型类,类似于Stack Community在

中建议我如何使用
字符串文本
而不是枚举

我猜您正在使用
enums
来避免打字错误,并且希望TypeScript为您“捕获”它。因此,如果您使用
字符串文本
,您是类型安全的,并且您将使用相同的“语言”与服务器对话

例如:

export type Sex = 'male' | 'female';
var sex: Sex = 'mela'; // Typo => ERROR from typescript

使用
字符串文本
而不是枚举如何

我猜您正在使用
enums
来避免打字错误,并且希望TypeScript为您“捕获”它。因此,如果您使用
字符串文本
,您是类型安全的,并且您将使用相同的“语言”与服务器对话

例如:

export type Sex = 'male' | 'female';
var sex: Sex = 'mela'; // Typo => ERROR from typescript

您可以创建一个类似于对象的函数:

// Return type is a bit more tricky because we have to get the enum type from typeof enum
function fromValue<T>(o: T, value: string): { [P in keyof T]: T[P]  }[keyof T]{
    return  (o as any)[value]; // No type safety here unfrotunately
}

var value = fromValue(MyEnum, ""); //value will be of type MyEnum
//返回类型有点棘手,因为我们必须从typeof enum中获取枚举类型
函数fromValue(o:T,value:string):{[P in keyof T]:T[P]}[keyof T]{
return(o as any)[value];//此处没有类型安全性
}
var value=fromValue(MyEnum,“”)//值的类型将为MyEnum

您可以创建与对象类似的函数:

// Return type is a bit more tricky because we have to get the enum type from typeof enum
function fromValue<T>(o: T, value: string): { [P in keyof T]: T[P]  }[keyof T]{
    return  (o as any)[value]; // No type safety here unfrotunately
}

var value = fromValue(MyEnum, ""); //value will be of type MyEnum
//返回类型有点棘手,因为我们必须从typeof enum中获取枚举类型
函数fromValue(o:T,value:string):{[P in keyof T]:T[P]}[keyof T]{
return(o as any)[value];//此处没有类型安全性
}
var value=fromValue(MyEnum,“”)//值的类型将为MyEnum

除了Titan给出的完美答案之外,这里还有一个小小的调整,可以同时处理您希望从/映射到哪种类型的值(字符串或数字)和希望得到哪种统一结果(字符串或数字):

enum MyEnum{
“VAL_ONE”=0,
“VAL_TWO”=1
}
函数fromValuetoNumber(o:T,value:string | number):{[P in keyof T]:T[P]}{
如果(类型(值)=“字符串”){
返回值(o为T)[值];
}else if(类型(值)=“数字”){
返回值(o为T)[o[值]]
}   
}
函数fromValueToString(o:T,value:string | number):{[P in keyof T]:T[P]}{
如果(类型(值)=“字符串”){
返回值(o为T)[o[值]];
}else if(类型(值)=“数字”){
返回值(o为T)[值]
}   
}
log(fromValuetoNumber(MyEnum'VAL_ONE'))
console.log(fromValuetoNumber(MyEnum,0))
log(从valuetoString(MyEnum'VAL_ONE'))
console.log(从ValueToString(MyEnum,0))
唯一让我困扰的是,若要分配泛型类型,TypeScript会变得疯狂:

fromValueToString<MyEnum>(MyEnum, 'VAL_ONE')
fromValueToString(MyEnum'VAL_ONE')

不过,这只是对原始答案的补充

除了Titan给出的完美答案之外,这里还有一个小小的调整,可以在您希望从/映射到哪种类型的值(字符串或数字)和希望得到哪种统一的结果(字符串或数字)两个方面发挥作用:

enum MyEnum{
“VAL_ONE”=0,
“VAL_TWO”=1
}
函数fromValuetoNumber(o:T,value:string | number):{[P in keyof T]:T[P]}{
如果(类型(值)=“字符串”){
返回值(o为T)[值];
}else if(类型(值)=“数字”){
返回值(o为T)[o[值]]
}   
}
函数fromValueToString(o:T,value:string | number):{[P in keyof T]:T[P]}{
如果(类型(值)=“字符串”){
返回值(o为T)[o[值]];
}else if(类型(值)=“数字”){
返回值(o为T)[值]
}   
}
log(fromValuetoNumber(MyEnum'VAL_ONE'))
console.log(fromValuetoNumber(MyEnum,0))
log(从valuetoString(MyEnum'VAL_ONE'))
console.log(从ValueToString(MyEnum,0))
唯一让我困扰的是,若要分配泛型类型,TypeScript会变得疯狂:

fromValueToString<MyEnum>(MyEnum, 'VAL_ONE')
fromValueToString(MyEnum'VAL_ONE')

不过,这只是对原始答案的补充

使用
ts enum util
(,),您可以通过运行时验证在枚举值和名称(在任意方向)之间执行类型安全转换。如果在运行时遇到无效值,您可以在抛出错误或返回默认值(默认情况下未定义)的方法变体之间进行选择

例如:

import {$enum} from "ts-enum-util";

enum MyEnum {
    FOO = 0,
    BAR = 1
}

function getMyEnum1(apiString: string): MyEnum {
    // throws informative error if "apiString" is not 
    // "FOO" or "BAR"
    return $enum(MyEnum).getValueOrThrow(apiString);
}

function getMyEnum2(apiString: string): MyEnum {
    // returns MyEnum.FOO if "apiString" is not 
    // "FOO" or "BAR"
    return $enum(MyEnum).getValueOrDefault(apiString, MyEnum.FOO);
}

function getMyEnum3(apiString: string): MyEnum | undefined {
    // returns undefined if "apiString" is not 
    // "FOO" or "BAR"
    return $enum(MyEnum).getValueOrDefault(apiString);
}

// type: ("FOO" | "BAR")
// value: "BAR"
const enumName = $enum(MyEnum).getKeyOrThrow(1);

使用
ts enum util
(,),可以通过运行时验证在枚举值和名称之间(在任意方向)执行类型安全转换。如果在运行时遇到无效值,您可以在抛出错误或返回默认值(默认情况下未定义)的方法变体之间进行选择

例如:

import {$enum} from "ts-enum-util";

enum MyEnum {
    FOO = 0,
    BAR = 1
}

function getMyEnum1(apiString: string): MyEnum {
    // throws informative error if "apiString" is not 
    // "FOO" or "BAR"
    return $enum(MyEnum).getValueOrThrow(apiString);
}

function getMyEnum2(apiString: string): MyEnum {
    // returns MyEnum.FOO if "apiString" is not 
    // "FOO" or "BAR"
    return $enum(MyEnum).getValueOrDefault(apiString, MyEnum.FOO);
}

function getMyEnum3(apiString: string): MyEnum | undefined {
    // returns undefined if "apiString" is not 
    // "FOO" or "BAR"
    return $enum(MyEnum).getValueOrDefault(apiString);
}

// type: ("FOO" | "BAR")
// value: "BAR"
const enumName = $enum(MyEnum).getKeyOrThrow(1);

恐怕这样简单的转换是不可能的,因为我们在另一个主要用例中使用它们,数组索引化。在这种情况下,将它们更改为字符串文字(一般来说,我同意,为了简单起见,这将是有益的)将使我们的生活变得更加艰难。我担心这样简单的转换是不可能的,因为我们在另一个主要使用情况中使用它们,数组索引化。在这种情况下,将它们更改为字符串文字(一般来说,我同意,为了简单起见,这将是有益的)将使我们的生活更加艰难。。。这绝对不相似;)工作起来很有魅力。我有个问题,
[keyof T]
代表什么?除此之外,我还看到,
keyof
是一个。。。这是解决问题的关键。再次感谢您!好。。。这绝对不相似;)工作起来很有魅力。我有个问题,
[keyof T]
代表什么?除此之外,我还记得