简体   繁体   English

Typescript:在通用类型约束中推断通用类型

[英]Typescript: infer generic types in generic type constraint

I have a generic interface that takes a type argument that must extend another generic type.我有一个通用接口,它接受一个必须扩展另一个通用类型的类型参数。 For example:例如:

export interface IPoint<TX, TY>
{
    x: TX;
    y: TY;
}
export interface ISeries<TPoint extends IPoint>
{
    points: Array<TPoint>;
}

Here, I must specify TX and TY for IPoint .在这里,我必须为IPoint指定TXTY

My question is: is there a way to infer those types automatically, for example like this?我的问题是:有没有办法自动推断这些类型,例如像这样?

export interface ISeries<TPoint extends IPoint<infer TX, infer TY>>
{
    points: Array<TPoint>;
}

The only way to make this work I've found for now is to add TX and TY as type parameters for ISeries , but it's quite impractical because then I have to specify the three types every time I use the interface.我目前发现的使这项工作起作用的唯一方法是将TXTY添加为ISeries的类型参数,但这是非常不切实际的,因为每次使用该接口时我都必须指定这三种类型。

I could also use IPoint<any, any> , but then I lose the information about the real types of x and y .我也可以使用IPoint<any, any> ,但是我丢失了有关xy的真实类型的信息。

EDIT: To add some clarification about what I want to achieve, let's consider the following example:编辑:为了澄清我想要实现的目标,让我们考虑以下示例:

export interface ISeries<TPoint extends IPoint<infer TX, infer TY>>
{
    points: Array<TPoint>;
    transformYValues?: (yValue: TY) => number;
}

Here I would need TY to strongly type transformYValues .在这里我需要TY来强类型transformYValues

Thanks for your help谢谢你的帮助

EDIT 2: Found a solution (thanks captain-yossarianfromUkraine).编辑 2:找到解决方案(感谢来自乌克兰的 captain-yossarian)。

export interface ISeries<TPoint extends IPoint<any, any>>
{
    points: Array<TPoint>;
    transformYValues?: (yValue: TPoint['y']) => number;
}

The key here is TPoint['y'] , I wasn't aware of this neat feature called Indexed Access Types (see https://www.typescriptlang.org/docs/handbook/2/indexed-access-types.html ).这里的关键是TPoint['y'] ,我不知道这个称为索引访问类型的简洁功能(请参阅https://www.typescriptlang.org/docs/handbook/2/indexed-access-types.html ) .

In summary => use any typing in the generic type constraints, then use indexed access types to strongly type methods/properties inside the interface.总之 => 在泛型类型约束中使用any类型,然后使用索引访问类型在接口内强类型化方法/属性。

Consider this example:考虑这个例子:

export interface Point<X, Y> {
  x: X;
  y: Y;
}

type Values = string | number

export interface Series<Points extends Point<Values, Values>[]> {
  points: Points;
  transformYValues: (yValue: Points[number]['y']) => number;
}

const inference = <
  X extends Values,
  Y extends Values,
  Points extends Point<X, Y>[]
>(data: Series<[...Points]>) => void 0


inference({
  points: [{ x: 1, y: 2 }, { x: 1, y: 9 }],
  transformYValues: (arg) => {
    arg // 2 | 9
    return 42
  }
})

PLayground操场

I added Values type as a constraint for allowed x and y data types.我添加了Values类型作为允许的xy数据类型的约束。

Also, I have added a function inference because type inference works with generic conditional types and function arguments.此外,我添加了一个 function inference ,因为类型推理适用于通用条件类型和 function arguments。

To infer literal type x:1 y:2 I have used variadic tuple types , see this [...Points]要推断文字类型x:1 y:2我使用了可变元组类型,请参阅此[...Points]

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

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