具有通用返回类型的 Typescript 函数 [英] Typescript Function with Generic Return Type

查看:35
本文介绍了具有通用返回类型的 Typescript 函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

type FuncGenericReturn = <T>() => T;
const funcReturnsNumber: FuncGenericReturn = (): number => 1;

(

(Sandbox)

出现此错误:

类型 'number' 不能分配给类型 'T'.数字"可分配给T"类型的约束,但T"可以使用约束{}"的不同子类型进行实例化.(2322)input.ts(1, 26):预期类型来自此签名的返回类型.

Type 'number' is not assignable to type 'T'. 'number' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{}'.(2322) input.ts(1, 26): The expected type comes from the return type of this signature.

我希望打字稿自动将 T 推断为数字并使用它.它为什么抱怨?写这样的东西的正确方法是什么?谢谢.

I would expect typescript to automatically infer T as number and just use it. Why is it complaining? What is the proper way to write something like this? Thanks.

推荐答案

重要的是要注意泛型类型参数的声明位置以及它们的作用域.类型

It's important to pay attention to where the generic type parameters are declared and what scope they have. The type

type FuncGenericReturn = <T>() => T;

是一个具体类型,指的是一个泛型函数.<代码>() =>T 的意思是:一个函数,它的调用者指定了一个 T 类型并返回一个 T 类型的值."这基本上不可能安全地实施.想象一下,如果你有这样的功能:

is a concrete type referring to a generic function. <T>() => T means: "a function whose caller specifies a type T and which returns a value of type T." This is essentially impossible to implement safely. Imagine if you had such a function:

declare const funcGenericReturn: FuncGenericReturn;

那么你应该可以这样称呼它:

Then you should be able to call it this way:

const someNumber: number = funcGenericReturn<number>(); 
const someString: string = funcGenericReturn<string>();

当然在运行时这些都会编译为

But of course at runtime those will both compile to

const someNumber = funcGenericReturn();
const someString = funcGenericReturn();

意味着 funcGenericReturn() 只需要在运行时知道"它应该首先返回一个 number 然后返回一个 string,基于在 JavaScript 之前擦除的类型信息生成.因此,正确实现 FuncGenericReturn 需要神奇的预知.

Meaning that funcGenericReturn() would just have to "know" at runtime that it should first return a number and then a string, based on type information which is erased before the JavaScript is generated. So properly implementing a FuncGenericReturn would require magical foreknowledge.

重申:当你有一个泛型函数时,泛型类型参数是由调用者指定的,而不是由实现者指定的.确实,有时编译器会推断这些类型参数,这样编写代码的人就不必将其拼写出来,但同样,这些推断发生在调用时.对同一个泛型函数的两次不同调用最终可能会导致类型参数有两种不同的选择.

To reiterate: when you have a generic function, the generic type parameters are specified by the caller, not by the implementer. It's true that sometimes the compiler will infer these type parameters so that the person writing the code doesn't have to spell it out, but again, these inferences are happening at call time. Two different calls to the same generic function could end up having two different choices for the type parameters.

让我们将其与不同但相关的类型定义进行比较:

Let's compare this to a different but related type definition:

type FuncConcreteReturn<T> = () => T;

这里,FuncConcreteReturn 是一个泛型类型,指的是一个具体函数.更准确地说 FuncConcreteReturn 不是真正的类型;它更像是一个类型运算符,它接受一个输入类型T并产生一个输出类型() =>.

Here, FuncConcreteReturn is a generic type referring to a concrete function. It would be more accurate to say that FuncConcreteReturn is not really a type; it's more like a type operator which takes an input type T and produces an output type () => T.

对于任何特定类型 T,类型 FuncConcreteReturn 是一个 concrete 函数类型,它不带参数并返回值输入 T.所以 FuncConcreteReturn 是一个不带参数并返回 string 的函数,而 FuncConcreteReturn 是一个函数,它接受没有参数并返回一个 number.请注意,FuncConcreteReturnFuncContreteReturn 是不同的类型,它们都不是 FuncConcreteReturn,因为那不是有效类型.所以以下是有效的:

For any particular type T, the type FuncConcreteReturn<T> is a concrete function type which takes no parameter and returns a value of type T. So a FuncConcreteReturn<string> is a function that takes no arguments and returns a string, while a FuncConcreteReturn<number> is a function that takes no arguments and returns a number. Note that FuncConcreteReturn<string> is a different type from FuncContreteReturn<number>, and neither of them are a FuncConcreteReturn because that's not a valid type. So the following is valid:

const funcReturnsNumber: FuncConcreteReturn<number> = () => 1;
const funcReturnsString: FuncConcreteReturn<string> = () => "";

同样,funcReturnsNumber 不是一个通用函数.它是一个始终返回数字的具体函数.而FuncConcreteReturn是一个泛型类型,其中T的值是在写出类型的时候选择的.由于这些类型是函数类型,类型 T 由这些函数的实现者选择,而不是由调用者选择.

Again, funcReturnsNumber is not a generic function. It is a concrete function that always returns a number. And FuncConcreteReturn<T> is a generic type, where the value of T is chosen when the type is written out. Since these types are function types, the type T is chosen by the implementer of these functions, and not by the caller.

顺便说一下,泛型函数类型之间的关系就像

By the way, the relationship between a generic function type like

type G = <T, U>(t: T, u: U) => [T, U]

和一个像

type H<T, U> = (t: T, u: U) => [T, U]

是后者的任何实例都将是前者的实例,但反之则不然.这意味着如果您确实有一个 FuncGenericReturn,您可以将它分配给 FuncConcreteReturnFuncConcreteReturn 类型的值;数字>:

is that any instance of the latter will be an instance of the former, but not vice versa. This means that if you did have a FuncGenericReturn, you could assign it to a value of type FuncConcreteReturn<string> or a FuncConcreteReturn<number>:

const fn: FuncConcreteReturn<number> = funcGenericReturn; // okay
const fs: FuncConcreteReturn<string> = funcGenericReturn; // okay

或者,对于上面的 GH 类型,您可以这样做:

Or, for the G and H types above, you could do this:

const g: G = <T, U>(t: T, u: U) => [t, u];
g("a", 1); // okay
g(1, "a"); // okay

const h1: H<string, number> = g; // okay
h1("a", 1); // okay
h1(1, "a"); // error

const h2: H<number, string> = g; // okay
h2(1, "a"); // okay
h2("a", 1); // error

<小时>

好的,我希望能让您对泛型函数和泛型类型之间的区别有所了解.祝你好运!


Okay, I hope that gives you some understanding on the difference between generic functions and generic types. Good luck!

游乐场连结代码

这篇关于具有通用返回类型的 Typescript 函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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