简体   繁体   English

描述参数的泛型类型,可以是少数类型之一

[英]A generic type to describe argument which can be one of few types

This question mainly comes from my previous one on this topic: Declare a custom type for logical argument这个问题主要来自我之前关于这个话题的一个问题: Declare a custom type for logical argument

Here an example:这里有一个例子:

interface ProductType1 {
  id: string;
}

interface ProductType2 {
  productId: string
}

function getId(product: ???): string {
  return product.id || product.productId || string
}

The idea behind this is straight forward: You can pass an object of a type ProductType1 or ProductType2 or a product id itself ( string )这背后的想法很简单:您可以传递ProductType1ProductType2类型的 object 或产品 ID 本身( string

I was trying to do something like:我试图做类似的事情:

type ProductAsArgument = ProductType1 | ProductType2 | string

or或者

interface Product {
  id: string;
  productId: string;
}

or或者

interface Product {
  id?: string;
  productId?: string;
}

But as you might guess none of this worked since one of the properties never exist on one of the union types ( ProductType1 , ProductType2 , string )但正如您可能猜到的那样,这些都不起作用,因为其中一个属性永远不会存在于其中一种联合类型( ProductType1ProductType2string

I believe my go-to option is to create some kind of a smart generic that will inherit a <T> and will know, that <T> can be either on of the types I mentioned above.我相信我的首选选项是创建某种智能泛型,它将继承<T>并且会知道<T>可以是我上面提到的类型之一。 I might be wrong here but it looks like to me that generic can solve this issue.我在这里可能错了,但在我看来,通用可以解决这个问题。

I found some interesting approaches here How to make one generic type closely dependent on another in TypeScript?我在这里找到了一些有趣的方法如何使 TypeScript 中的一个泛型类型紧密依赖于另一个泛型类型? but still don't understand how to apply it on my case但仍然不明白如何将其应用于我的案例

Can you use classes instead of interfaces?你可以使用类而不是接口吗? In which case you can do something like this, although it would be cleaner to use inheritance for the ProductType classes:在这种情况下,您可以执行以下操作,尽管将 inheritance 用于 ProductType 类会更简洁:

Using Classes使用类

class ProductType1 {
  id: string = '1';
}

class ProductType2 {
  productId: string = '2';
}

type ProductOrString = ProductType1|ProductType2|string;

function getId(product: ProductOrString): string {
  if (product instanceof ProductType1)
    return product.id;
  else if (product instanceof ProductType2)
    return product.productId;
  else if (typeof product === 'string')
    return product;
  else
    return 'Error in getId(): Unexpected type';
}

let prod1 = new ProductType1();
let prod2 = new ProductType2();
let prod3 = '3';

console.log(`prod1 ID is ${getId(prod1)}`);
console.log(`prod2 ID is ${getId(prod2)}`);
console.log(`prod3 ID is ${getId(prod3)}`);

TS Playground link TS Playground 链接


Alternatively, using interfaces:或者,使用接口:

Using Interfaces使用接口

interface ProductType1 {
  id: string;
}

interface ProductType2 {
  productId: string;
}

type ProductOrString = ProductType1|ProductType2|string;

function getId(product: ProductOrString): string {
  if (typeof product === 'string')
    return product;
  else
  if ('id' in product)
    return product.id;
  else if ('productId' in product)
    return product.productId;
  else
    return 'getId(): Unexpected type';
}

let prod1 = { id: '1' };
let prod2 = { productId: '2' };
let prod3 = '3';

console.log(`prod1 ID is ${getId(prod1)}`);
console.log(`prod2 ID is ${getId(prod2)}`);
console.log(`prod3 ID is ${getId(prod3)}`);

Another solution using generics:使用 generics 的另一种解决方案:

type Nullish<T> = T|null|undefined;
type ObjOrStr<T> = T|string;

abstract class BaseProduct
{
    id: Nullish<string>;
    productId: Nullish<string>;
}

class Product1 extends BaseProduct
{
    id: string = 'id1';
}

class Product2 extends BaseProduct
{
    productId: string = 'productId2';
}

class SomeClass
{
    getProductId<T extends BaseProduct>(product: ObjOrStr<T>)
    {
        if (typeof product === 'string')
            return product;
        else
            return product.id || product.productId;
    }

    someMethod<T extends BaseProduct>(product: ObjOrStr<T>)
    {
        const productName = this.getProductId(product);

        return productName;
    }
}

let prod1 = new Product1();
let prod2 = new Product2();
let prod3 = 'string3';
let sc = new SomeClass();

console.log(`prod1 id = ${sc.someMethod(prod1)}`);
console.log(`prod2 id = ${sc.someMethod(prod2)}`);
console.log(`prod3 id = ${sc.someMethod(prod3)}`);

TS playground link TS游乐场链接

I'm not going to directly answer your question.我不会直接回答你的问题。 But for this type of problem但是对于这类问题

You can pass an object of a type ProductType1 or ProductType2 or a product id itself (string).

I will have gone in the direction of functions overriding.我将朝着功能覆盖的方向发展。

function getId(productId: string): string
function getId(product: ProductType1): string
function getId(product: ProductType2): string
function getId(product: string | ProductType1 | ProductType2): string {
  if (typeof product === "string")
    return product;
  else if (product instanceof ProductType1)
    ...
}

All you need to do is type them您需要做的就是输入它们

interface ProductType1 {
  id: string;
}

interface ProductType2 {
  productId: string
}

function getId(product: ProductType1 | ProductType2 | string): string {
  return (product as ProductType1).id || (product as ProductType2).productId || product as string
}

You can also choose to do typeof product == 'ProductType1' if statements..你也可以选择做typeof product == 'ProductType1' if statements..

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

相关问题 如何使用基于泛型类型的条件类型来描述约束? - How to describe constraint using conditional type which is based on generic type? 我可以有一个包含其他类型小节的泛型类型吗? - Can I have a generic type which contains a subsection of other types? 从函数参数中推断出一种泛型类型 - Infer one of generic types from function argument 检查泛型函数参数中的类型并返回此参数的对象字面量类型 - Check types in argument of generic function and return object literal type of this argument 在不指定泛型参数的情况下缩小为keyof类型的泛型类型 - Narrowing generic type which is keyof type without specifying generic argument Typescript泛型中的约束类型为几种类型之一 - Constraining type in Typescript generic to be one of several types 通用类型的观察者 <T> 需要1种类型的参数 - Generic type Observer<T> requires 1 types argument(s) 无法将特定类型作为参数分配给泛型 - Can't assign specific type as an argument to a generic 如何描述 function 的返回类型,这是通过通用 function 调用的结果 - How to describe return type of function which is result of call passed generic function 将具有两种泛型类型的泛型接口组合为仅具有一种泛型类型的一种类型 - Combine generic interfaces with two generic types into one type with only one generic type
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM