简体   繁体   English

编写通用联合体类型的吸气剂

[英]Writing a getter of generic union type

From a union of two generic types I want to return the left value (or a default value if the union has the right type). 从两个通用类型的联合中,我想返回左值(如果联合具有正确的类型,则返回默认值)。 I tried but generics and typeof / instanceof seems to not work so great together. 我尝试过,但泛型和typeof / instanceof似乎不能很好地协同工作。

This is how I would write it in Haskell: 这就是我在Haskell中写的方式:

data Either a b = Left a | Right b

getLeftOrDefault :: a -> Either a b -> a
getLeftOrDefault _ (Left a) = a
getLeftOrDefault a (Right b) = a

and how would this translate to Typescript? 以及如何将其转换为Typescript? This was my try: 这是我的尝试:

function getLeftOrDefault<A, B>(either: A | B, backup: A) {
  if (either instanceof A) {
     return either;
  }
  return backup;
}

But this does not work. 但这是行不通的。 Any other way or workaround? 还有其他方法或解决方法吗?

TypeScript types exist only at compile-time (since Javascript has no notion of types). TypeScript类型仅在编译时存在(因为Javascript没有类型概念)。

Therefore, you can't use type parameters at runtime. 因此,您不能在运行时使用类型参数。

Instead, you can check if (either instanceof backup.constructor) , which is an easy way to get the A constructor at runtime. 相反,您可以检查if (either instanceof backup.constructor) ,这是在运行时获取A构造函数的简便方法。

Note that this will not work for primitives. 请注意,这不适用于原语。

As https://stackoverflow.com/a/51329983/6656422 states there are no TypeScript types at run time. https://stackoverflow.com/a/51329983/6656422所述,运行时没有TypeScript类型。 You have to test the "type". 您必须测试“类型”。 To make something generic you could pass in a tester. 要使通用的东西可以通过测试器。

function getLeftOrDefault<A, B>(either: A | B, backup: A, isA: (obj: any) => obj is A): A {
  if (isA(either)) {
    return either;
  }
  return backup;
}

Usage: 用法:

Many times interfaces are used for strongly typing object literals, you can test the property(ies). 很多时候,接口都用于强类型化对象文字,您可以测试属性。

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' }

If your types are classes they have constructors at run time. 如果您的类型是类,则它们在运行时具有构造函数。

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' }

However constructor checking is not fool proof because of casting 但是,由于强制转换,构造函数检查不是万无一失的

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' }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM