简体   繁体   English

Typescript - 如何在未调用的 function 中推断泛型?

[英]Typescript - How to infer generic in non-invoked function?

See the example below;请参见下面的示例; it should be working by all reasonable interpretation of the code.它应该通过对代码的所有合理解释来工作。 Does anybody have any insight on why it doesn't?有没有人知道为什么没有?

TS-playground link TS-游乐场链接


const func_returnsInput = (input: string) : Promise<string> => Promise.resolve(input);

type returnsInput_T = <T>(data: T) => Promise<T>;

const test: returnsInput_T = func_returnsInput;

**ERROR**
Type '(input: string) => Promise<string>' is not assignable to type 'returnsInput_T'.
  Types of parameters 'input' and 'data' are incompatible.
    Type 'T' is not assignable to type 'string'.(2322)

The type signature of func_returnsInput is: func_returnsInput的类型签名是:

const func_returnsInput: (input: string) => Promise<string>

That is specifically a function that accepts a string (and only a string ) and returns a Promise<string> .这是一个 function 接受一个string (并且只接受一个string )并返回一个Promise<string> You could change the implementation slightly and it would still conform to the annotated type signature:您可以稍微更改实现,它仍然符合带注释的类型签名:

const func_returnsInput = (input: string): Promise<string> =>
    Promise.resolve(input.toUpperCase());

The fact that the implementation doesn't do that is not important to the compiler.实现不这样做的事实对编译器并不重要。 It considers the call signature to be the externally-viewable type of the function, and any specific implementation to be hidden.它认为调用签名是 function 的外部可见类型,并且隐藏任何具体实现。 If someone hands me func_returnsInput , all I know is that it takes a string and returns a Promise<string> .如果有人递给我func_returnsInput ,我所知道的是它接受一个string并返回一个Promise<string> If I were to feed it, say, a number , then I have done something wrong.如果我要给它喂一个number ,那么我做错了什么。


Contrast that now with the type ReturnsInput_T :现在将其与ReturnsInput_T类型进行对比:

type ReturnsInput_T = <T>(data: T) => Promise<T>;

That is a generic call signature with a generic type parameter T .这是一个带有泛型类型参数T泛型调用签名。 The type parameter may be specified at will by the caller of the function, not by the implementer of the function. The type ReturnsInput_T is a function that accepts any value the caller wants (say, a number ), and then returns a Promise of the same data type (so, Promise<number> ).类型参数可以由 function 的调用者随意指定,而不是由 function 的实现者指定。类型ReturnsInput_T是一个 function,它接受调用者想要的任何值(比如,一个number ),然后返回一个Promise相同的数据类型(因此, Promise<number> )。

If it helps, you can think of a generic call signature as an infinite intersection of all possible types for T .如果有帮助,您可以将通用调用签名视为T的所有可能类型的无限交集 You can't write that out, but it behaves like你不能把它写出来,但它的行为就像

type ReturnsInput_T_Infinite =
    & ((data: string) => Promise<string>) 
    & ((data: number) => Promise<number>)
    & ((data: boolean) => Promise<boolean>)
    & ((data: Date) => Promise<Date>)
    & ((data: null) => Promise<null>)
    // & ...

Now it hopefully makes sense why you cannot assign func_returnsInput to a value of type ReturnsInput :现在,为什么不能将func_returnsInput分配给ReturnsInput类型的值,这很有可能是有道理的:

const test: ReturnsInput_T = func_returnsInput; // error!
// Type 'T' is not assignable to type 'string'.

test(123); // no error

If test is truly of type ReturnsInput_T , then I should be allowed to call test(123) , or test(false) or test(new Date()) or anything I want, and get back a Promise of the same data type.如果test确实是ReturnsInput_T类型,那么我应该被允许调用test(123)test(false)test(new Date())或任何我想要的,并取回相同数据类型的Promise But func_returnsInput cannot be known to do that by the compiler (even if the implementation happens to do this).但是编译器不知道func_returnsInput (即使实现恰好这样做)。

And so you get an error!所以你得到一个错误!

Playground link to code 游乐场代码链接

I think the problem is that you want to use the type of a function that takes a generic with a function that takes explicitly a string.我认为问题在于您想要使用带有泛型的 function 类型和带有显式字符串的 function 类型。 The following works for me:以下对我有用:

type returnsInput_T = <T>(data: T) => Promise<T>;


function func_returnsInput<T>(input: T) {
    return Promise.resolve(input)
}

const test: returnsInput_T = func_returnsInput; 

Hope it helped希望对您有所帮助

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

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