[英]Typescript - conditional types based on value in a for of list
So these are my types:所以这些是我的类型:
export type typeOne = {
A: string;
B: string;
};
export type typeTwo = {
A: string;
C: string;
};
export type Result = typeOne | typeTwo; //condition
And this is the use case:这是用例:
for (const item: Result of list) {
const something = item.B ? 'B exsist' : item.C;
return something;
}
It keeps returning error:它不断返回错误:
TS2339: Property 'B' does not exist on type 'Result'.
TS2339:“结果”类型上不存在属性“B”。 Property 'B' does not exist on type 'typeTwo'.
类型“typeTwo”上不存在属性“B”。
and also for the other one:还有另一个:
TS2339: Property 'C' does not exist on type 'Result'.
TS2339:“结果”类型上不存在属性“C”。 Property 'C' does not exist on type 'typeOne'.
类型“typeOne”上不存在属性“C”。
Do you have any idea how can I fix this?你知道我该如何解决这个问题吗?
Note : The following error is also happening for the loop:注意:循环也会发生以下错误:
TS2483: The left-hand side of a 'for...of' statement cannot use a type annotation.
TS2483:“for...of”语句的左侧不能使用类型注释。
You can use an in
type guard to discriminate a union of object types with unequal keys:您可以使用
in
类型保护来区分具有不相等键的对象类型的联合:
for (const item: Result of list) {
const something = "B" in item ? 'B exsist' : item.C;
return something;
}
One of the nuances of TypeScript is that if you have a union type of objects, you can only access the fields that are common between them. TypeScript 的一个细微差别是,如果你有一个联合类型的对象,你只能访问它们之间的公共字段。 It is common to use this technique to add a common field that can tell the two apart.
使用这种技术来添加一个可以区分两者的公共字段是很常见的。 For instance:
例如:
export type typeOne = {
type: 'one';
A: string;
B: string;
};
export type typeTwo = {
type: 'two'
A: string;
C: string;
};
export type Result = typeOne | typeTwo; //condition
for (const item: Result of list) {
const something = item.type === 'one' ? 'B exists' : item.C;
return something;
}
In this case, type
acts as a discriminator.在这种情况下,
type
充当鉴别器。 Read more here: https://basarat.gitbook.io/typescript/type-system/discriminated-unions在此处阅读更多信息: https : //basarat.gitbook.io/typescript/type-system/discriminated-unions
Alternatively, you can create a custom type guard to differentiate between the two types.或者,您可以创建自定义类型保护来区分这两种类型。 This involves a function that takes your union type and evaluates at runtime if the value is of a particular type.
这涉及一个函数,该函数接受您的联合类型并在运行时评估该值是否为特定类型。 You can use a type assertion to access a non-shared field in the union:
您可以使用类型断言访问联合中的非共享字段:
function isTypeOne(result: Result): result is typeOne {
return (result as typeOne).B !== undefined;
}
for (const item: Result of list) {
const something = isTypeOne(item) ? 'B exists' : item.C;
return something;
}
Here, if isTypeOne
fails, typeOne
can be safely eliminated from Result
, thus the type is inferred as typeTwo
.在这里,如果
isTypeOne
失败, typeOne
可以安全地从Result
消除,因此类型被推断为typeTwo
。
Regarding the last error you mentioned:关于您提到的最后一个错误:
"TS2483: The left-hand side of a 'for...of' statement cannot use a type annotation."
“TS2483:'for...of' 语句的左侧不能使用类型注释。”
The Result
type definition should be part of your declaration of list
. Result
类型定义应该是list
声明的一部分。 That way, there is no need to specify that the left-hand side of the statement is a Result
.这样,就无需指定语句的左侧是
Result
。
For example, assuming list
is an array:例如,假设
list
是一个数组:
const list: Array<Result> = [{A: 'foo', B: 'bar'}, {A: 'foo', C: 'baz'}]
for (const item of list) {
// Run code from other answers here
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.