TypeScript如何为泛型函数创建泛型类型别名? [英] TypeScript how to create a generic type alias for a generic function?

查看:104
本文介绍了TypeScript如何为泛型函数创建泛型类型别名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

某个地方 可能已经回答了这个问题,但是我在查看六个问题和TypeScript问题时并没有发现它.

This has probably been answered somewhere, but I haven't found it in looking at a half-dozen questions and TypeScript issues.

给定一个类型化的泛型函数,我想为该函数创建一个泛型别名,但看来我做不到.换句话说,这是行不通的:

Given a typed generic function, I want to create a generic alias for that function, but it seems I can't. In other words, this doesn't work:

// foo.tsx
function foo<T>(arg: T): T {
  return arg
}

type FooT = typeof foo  // works, but alias isn't generic: <T>(arg: T) => T
type FooParametersT = Parameters<typeof foo>  // sure: [unknown]
type FooReturnT = ReturnType<typeof foo>  // no problem: unknown

type GFooT<T,> = typeof foo<T,>  // yikes
type GFooParametersT<T,> = Parameters<typeof foo<T,>>  // nope
type GFooReturnT<T,> = ReturnType<typeof foo<T,>>  // fails

我真正想做的是在别人的库中获取一个函数的类型,然后围绕它建立一个接口.例如:

What I'm really trying to do is grab the type of a function in someone else's library and then build an interface around it. For example:

import { useState } from "react"

type UseStateFnT<T,> = typeof useState<T>
const wrapUseState: (toWrap: UseStateFnT<T,>) => UseStateFnT<T,> = …

是否可以不重新创建我自己是复杂类型的函数签名?

推荐答案

TypeScript中有两种不同的泛型类型:泛型函数和泛型 types ...看起来您想让编译器为您将一个转换为另一个,而这并不是直接支持的.

There are two different flavors of generics in TypeScript: generic functions, and generic types... and it looks like you want the compiler to transform one into the other for you, which isn't directly supported.

要清楚:

泛型 types 具有类型参数,在将它们用作特定类型之前需要进行指定.例如:

Generic types have type parameters that need to be specified before you can use them as a specific type. For example:

type GenType<T> = (x: T) => T[];
declare const oops: GenType; // error
declare const genT: GenType<string>; // okay
const strArr = genT("hello"); // string[];
const numArr = genT(123); // error!

在这里,GenType是通用类型.您需要指定type参数以将其用作值的类型,然后生成的类型不再是通用的. genT函数采用string并返回string[].它不能用作接受number并返回number[]的函数.

Here, GenType is a generic type. You need to specify the type parameter to use it as the type of a value, and then the resulting type is no longer generic. The genT function takes a string and returns a string[]. It cannot be used as a function that takes a number and returns a number[].

通用功能具有特定的类型,可以像对其类型参数的任何可能替换一样起作用.泛型函数类型的值在您使用时仍然是泛型的. type参数附加到呼叫签名:

Generic functions, on the other hand, have a specific type that can act like any possible substitution of its type parameters. The value of a generic function type is still generic when you use it. The type parameter is attached to the call signature:

type GenFunc = <T>(x: T) => T[];
declare const genF: GenFunc;
const strArr = genF("hello"); // strArr: string[];
const numArr = genF(123); // numArr: number[];

在这里,GenFunc是指泛型函数的特定类型. genF函数在被调用时仍然是通用的.

Here, GenFunc is a specific type referring to a generic function. The genF function is still generic when it is called.

通用函数(包括通用构造函数)可以被视为通用值,而不是通用类型.

Generic functions (including generic constructor functions) can be thought of as generic values, as opposed to generic types.

这两种类型的泛型彼此相关,但是TypeScript类型系统的表达能力不足以谈论它们之间的关系.用其他某种语言,您也许可以像另一种一样定义一个

These two flavors of generics are related to each other but the TypeScript type system isn't expressive enough to talk about how they are related. In some other language, you might be able to define one in terms of the other like

type GenFunc = forall T, GenType<T>; // not TS, error

type GenType<T> = instantiate GenFunc with T; // not TS, error

,但是在TypeScript中不能.因此,不可能直接在类型系统中以编程方式将GenFunc转换为GenType.

but in TypeScript you can't. So it is not directly possible to turn GenFunc into GenType programmatically in the type system.

有很多邪恶的方法可以迫使编译器根据GenFunc来计算GenType.我所知道的方式利用了通用类属性初始化和一些

There are evil awful ways to coerce the compiler to calculate GenType in terms of GenFunc. The way I know of makes use of generic class property initialization and some higher order type inference for generic functions introduced in TypeScript 3.4. I'm making the compiler think it's calculating values when I don't actually have any, and then getting the type of one of these pretend values:

class GenTypeMaker<T> {
    getGenType!: <A extends any[], R>(cb: (...a: A) => R) => () => (...a: A) => R;
    genType = this.getGenType(null! as GenFunc)<T>()
}
type GenType2<T> = GenTypeMaker<T>['genType']
// type GenType2<T> = (x: T) => T[]

您可以验证GenType2<T>GenType<T>的类型相同,并且如果将GenFunc更改为具有一个类型参数的任何泛型函数,则GenType2<T>也会相应地更改.但是我不知道我是否要推荐任何实际使用此方法的人.

You can verify that GenType2<T> is the same type as GenType<T>, and if you change GenFunc into any generic function with one type parameter, GenType2<T> will change accordingly. But I don't know I'd want to recommend anyone actually use this method.

无论如何,希望能有所帮助;祝你好运!

Anyway, hope that helps; good luck!

游乐场链接代码

这篇关于TypeScript如何为泛型函数创建泛型类型别名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆