[英]Typescript interface value as enum or Record
Suppose I have some object that could have either key
as string and value
as either enum
or object with key and value as enum.假设我有一些 object 可以将
key
作为字符串,将value
作为enum
或 object,将键和值作为枚举。
types类型
export enum ERRORS {
ERROR1 = 'Error1',
ERROR2 = 'Error2',
}
export type ErrorType = 'blue' | 'green';
export interface ErrorByCode {
[key: string]: ERRORS | Record<ErrorType, ERRORS>;
}
code代码
const ERRORS_BY_CODE: ErrorByCode = {
default: ERRORS.ERROR1,
'01': ERRORS.ERROR2,
'2': {
blue: ERRORS.ERROR1,
green: ERRORS.ERROR2,
},
};
const errorResolver = ({code, type}: {code: string; type: ERRORS}) => {
const errorMessage =
(ERRORS_BY_CODE?.[code] || ERRORS_BY_CODE?.[code]?.[type]) ??
ERRORS_COMPONENTS_BY_CODE.default;
return errorMessage
};
console.log(errorResolver({code: '01', type: 'blue'}))
But I've got ts error under ERRORS_BY_CODE?.[code]?.[type] Element implicitly has an 'any' type because expression of type 'ErrorType' can't be used to index type 'ERRORS |但是我在ERRORS_BY_CODE?.[code]?.[type]下出现 ts 错误,因为“ErrorType”类型的表达式不能用于索引类型“ERRORS | Record<ErrorType, ERRORS>'.
记录<错误类型,错误>'。 Property 'blue' does not exist on type 'ERRORS_BY_CODE |
类型 'ERRORS_BY_CODE | 上不存在属性'蓝色' Record<InsuranceType, ERROR_COMPONENTS>'.
记录<InsuranceType,ERROR_COMPONENTS>'。
The compiler does not expect anyone to try to index into a string
(which ERRORS
is) with a key like "blue"
, and it does not allow it.编译器不希望任何人尝试使用
"blue"
之类的键对string
( ERRORS
是)进行索引,并且它不允许这样做。 It will consider that property to be of type any
, and give a compile error:它将认为该属性的类型为
any
,并给出编译错误:
function nope(str: string) {
str.blue // error! Property 'blue' does not exist on type 'string'
}
If a value is of a type which is a union of string
and something else, the compiler will also be unhappy about such an indexing, since it might be a string
for all it knows:如果一个值的类型是
string
和其他东西的联合,编译器也会对这样的索引不满意,因为它可能是它所知道的所有string
:
function stillNope(uni: string | { blue: number }) {
uni.blue // error! Property 'blue' does not exist on type 'string'
}
Optional chaining does not fix this. 可选链接不能解决这个问题。 You are not allowed to access an unknown property on an object even if you use
?.
即使您使用
?.
instead of .
而不是
.
. . This prohibition is intentional;
这种禁止是故意的; see microsoft/TypeScript#33736 for more information.
有关详细信息,请参阅microsoft/TypeScript#33736 。
If you want to access a property on a union type where at least one of the members of the union is not known to have that property, you will need to use some other form of type guarding.如果要访问联合类型上的属性,其中至少有一个联合成员不知道具有该属性,则需要使用其他形式的类型保护。 One way is to use
typeof
guarding :一种方法是使用
typeof
保护:
function typeofGuard(
uni: ERRORS | { blue: ERRORS, green: ERRORS },
type: ErrorType
) {
const errors = typeof uni === "string" ? uni : uni[type];
}
The other possibility is to represent your union as one where each member of the union has known behavior at the ErrorType
keys.另一种可能性是将您的工会表示为工会的每个成员在
ErrorType
键上都有已知行为的工会。 Instead of ERRORS
, which is a string
with no known behavior at ErrorType
, you can make it ERRORS & {[P in ErrorType]?: undefined }
.而不是
ERRORS
,这是一个在ErrorType
没有已知行为的string
,您可以将其设为ERRORS & {[P in ErrorType]?: undefined }
。 Meaning: it is ERRORS
, and if you index into it with an ErrorType
key, you will get an undefined
property.含义:它是
ERRORS
,如果您使用ErrorType
键对其进行索引,您将获得一个undefined
的属性。 This makes your error go away also:这也会使您的错误 go 消失:
function exclusiveUnion(
uni: (ERRORS & { [P in ErrorType]?: undefined }) | (Record<ErrorType, ERRORS>),
type: ErrorType
) {
const errors = uni[type]; // ERRORS | undefined
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.