Typescript 检查后将a或B值设置为a值

Typescript 检查后将a或B值设置为a值,typescript,Typescript,我有一个值,可以是a型或B型,也可以是显式的a型: let valueOptional: A|B; let valueExplicit: A; 现在我进行一次类型检查,然后设置值: if ((typeof valueOptional).toString() === 'B') { valueExplicit = convertB2A(valueOptional); } else { valueExplicit = valueOptional; } 现在编译器仍然抛出此错误: Type

我有一个值,可以是a型或B型,也可以是显式的a型:

let valueOptional: A|B;
let valueExplicit: A;
现在我进行一次类型检查,然后设置值:

if ((typeof valueOptional).toString() === 'B') {
  valueExplicit = convertB2A(valueOptional);
} else {
  valueExplicit = valueOptional;
}
现在编译器仍然抛出此错误:

Type 'A | B' is not assignable to type 'A'.
  Type 'A' is not assignable to type 'B'.
    Property 'xyz' is missing in type 'B'.

有没有解决此问题的方法?

如果您有一个并集,并且希望将并集的类型缩小到它的一个组成部分,则需要使用类型保护。编译器对类型保护的理解是有限的,我们可以在给定类型上使用什么也取决于我们拥有什么类型的类型

对于原语,我们可以使用
typeof
类型保护:

let valueOptional: number|string;
let valueExplicit: number;

if (typeof valueOptional === 'number') {
  valueExplicit = valueOptional; // valueOptional is number here
} else {
  valueExplicit = +valueOptional //valueOptional is string and we convert
}
class A { constructor(public foo: number) { } }
class B { constructor(public bar: number) { } }
let valueOptional: A | B;
let valueExplicit: A;

if (valueOptional instanceof A) {
  valueExplicit = valueOptional; // valueOptional is A here
} else {
  valueExplicit = new A(valueOptional.bar) //valueOptional is B and we convert
}
对于类,我们可以使用
instanceof
类型保护:

let valueOptional: number|string;
let valueExplicit: number;

if (typeof valueOptional === 'number') {
  valueExplicit = valueOptional; // valueOptional is number here
} else {
  valueExplicit = +valueOptional //valueOptional is string and we convert
}
class A { constructor(public foo: number) { } }
class B { constructor(public bar: number) { } }
let valueOptional: A | B;
let valueExplicit: A;

if (valueOptional instanceof A) {
  valueExplicit = valueOptional; // valueOptional is A here
} else {
  valueExplicit = new A(valueOptional.bar) //valueOptional is B and we convert
}
如果
A
B
是接口,我们可以使用
类型保护中的
根据属性的存在来确定类型(无论
typeof
还是
instanceof
都不起作用,因为在运行时接口并没有真正以任何方式表示)。
类型保护中的
可以与类一起工作,但对于接口,它是唯一的选项:

interface A { foo: number }
interface B { bar: number }
let valueOptional: A | B;
let valueExplicit: A;

if ('foo' in valueOptional) {
  valueExplicit = valueOptional; // valueOptional is A here
} else {
  valueExplicit = { foo: valueOptional.bar } //valueOptional is B and we convert
}
如果条件更复杂,也可以使用自定义类型的防护:

interface A { foo: number }
interface B { foo: string }
let valueOptional: A | B;
let valueExplicit: A;
// any condition that returns true/false will do, used an arrow function but any function that returns param is type will act as a type guard.
const isA = <T>(v: T | A): v is A => typeof (v as A).foo === 'number'; 

if (isA(valueOptional)) {
  valueExplicit = valueOptional; // valueOptional is A here
} else {
  valueExplicit = { foo: +valueOptional.foo } //valueOptional is B and we convert
}
接口A{foo:number}
接口B{foo:string}
让值可选:A | B;
让我们明确一点:A;
//任何返回true/false的条件都可以,使用箭头函数,但任何返回param is type的函数都将充当类型保护。
常量isA=(v:T | A):v是A=>typeof(v作为A);
如果(isA(可选值)){
valueExplicit=valueOptional;//valueOptional在这里是一个
}否则{
valueExplicit={foo:+valueOptional.foo}//valueOptional是B,我们转换
}
您还可以混合和匹配类型防护装置:

interface A { foo: number }
interface B { foo: string }
class C { bar: string }
let valueOptional: number| A | B | C;
let valueExplicit: A;
const isA = <T>(v: T | A): v is A => typeof (v as A).foo === 'number'; 

if (typeof valueOptional === 'number') {
  valueExplicit = { foo: valueOptional }; // valueOptional is number here
}else if(valueOptional instanceof C) {
  valueExplicit = { foo: +valueOptional.bar } //valueOptional is C and we convert
} else if (isA(valueOptional)) {
  valueExplicit = valueOptional //valueOptional is A 
} else {
  valueExplicit = { foo: + valueOptional.foo } //valueOptional is B by elimination and we convert
}
接口A{foo:number}
接口B{foo:string}
类C{bar:string}
让值可选:编号| A | B | C;
让我们明确一点:A;
常量isA=(v:T | A):v是A=>typeof(v作为A);
如果(值的类型可选=='number'){
valueExplicit={foo:valueOptional};//valueOptional是这里的数字
}else if(值C的可选实例){
valueExplicit={foo:+valueOptional.bar}//valueOptional是C,我们转换
}else if(isA(可选值)){
valueExplicit=valueOptional//valueOptional是一个
}否则{
valueExplicit={foo:+valueOptional.foo}//valueOptional通过消去是B,我们转换
}

什么是A或B?这会影响您可以使用的类型保护的类型。。对于基本体,您可以使用
typeof x===“number”
对于类,您可以使用
x instanceof A
对于接口,您可以使用
中的
在x中的
'xyz'。。。这要看情况而定。但是您上面的构造
(typeof x).toString()='type'
不是类型保护
a
Params
B
是来自angulars路由器模块的
ParamMap
。因此,这两种类型都是
类型
类型也会在编译时被删除,因此可以是自定义类型保护或
类型保护中的
。。