从两个通用类型的联合中,我想返回左值(如果联合具有正确的类型,则返回默认值)。我尝试过,但泛型和typeof
/ instanceof
似乎不能很好地协同工作。
这就是我在Haskell中编写它的方式:
data Either a b = Left a | Right b
getLeftOrDefault :: a -> Either a b -> a
getLeftOrDefault _ (Left a) = a
getLeftOrDefault a (Right b) = a
,这将如何转换为Typescript? 这是我的尝试:
function getLeftOrDefault<A, B>(either: A | B, backup: A) {
if (either instanceof A) {
return either;
}
return backup;
}
但这不起作用。还有其他方法或解决方法吗?
答案 0 :(得分:1)
TypeScript类型仅在编译时存在(因为Javascript没有类型概念)。
因此,您不能在运行时使用类型参数。
相反,您可以检查if (either instanceof backup.constructor)
,这是在运行时获取A
构造函数的简便方法。
请注意,这不适用于基本体。
答案 1 :(得分:1)
根据https://stackoverflow.com/a/51329983/6656422的说明,运行时没有TypeScript类型。您必须测试“类型”。要使通用的东西可以通过测试器。
function getLeftOrDefault<A, B>(either: A | B, backup: A, isA: (obj: any) => obj is A): A {
if (isA(either)) {
return either;
}
return backup;
}
用法:
很多时候接口都用于强类型化对象文字,您可以测试属性。
interface Car {
engine: string;
}
interface Tree {
branches: any[];
}
function isCar(obj: any): obj is Car {
return !!obj.engine;
}
const myCar: Car = { engine: '350' };
const myTree: Tree = { branches: [] };
const myBackup: Car = { engine: '396' };
getLeftOrDefault(myCar, myBackup, isCar); // -> { engine: '350' }
getLeftOrDefault(myTree, myBackup, isCar); // -> { engine: '396' }
如果您的类型是类,则它们在运行时具有构造函数。
class Car {
constructor(public engine: string) {}
}
class Tree {
constructor(public branches: any[]) {}
}
function isCar(obj: any): obj is Car {
return obj instanceof Car;
}
const myCar: Car = new Car('350');
const myTree: Tree = new Tree([]);
const myBackup: Car = new Car('396');
getLeftOrDefault(myCar, myBackup, isCar); // -> { engine: '350' }
getLeftOrDefault(myTree, myBackup, isCar); // -> { engine: '396' }
但是,由于强制转换,构造函数检查并非万无一失
const myCar: Car = { engine: '350' };
const myTree: Tree = { branches: [] };
const myBackup: Car = { engine: '396' };
getLeftOrDefault(myCar, myBackup, isCar); // -> { engine: '396' }
getLeftOrDefault(myTree, myBackup, isCar); // -> { engine: '396' }