简体   繁体   English

如何在 Typescript 中定义泛型函数类型; 两种相似的方式?

[英]How to define a generic function type in Typescript; two similar ways?

I'm trying to define some generic function types in Typescript.我正在尝试在 Typescript 中定义一些通用函数类型。 It seems like there are two similar ways to do it, and they both kind-of work.似乎有两种类似的方法可以做到这一点,而且它们都有效。 However the second form - see below ConcatY - doesn't seem as flexible, or at least I don't know how to indicate that a function takes one of these with specific argument types.然而,第二种形式——见下文ConcatY似乎不那么灵活,或者至少我不知道如何表明一个函数采用其中一种具有特定参数类型。 Is there a way to define a function that takes a ConcatY for numbers?有没有办法定义一个采用ConcatY表示数字的函数? In general, how should I think about the differences between these two ways to define a generic function?一般来说,我应该如何考虑这两种定义泛型函数的方式之间的差异?

// Two similar looking function types
type ConcatX<T> = (a: T, b: T) => T;
type ConcatY = <T>(a: T, b: T) => T;

// Can create instances of each of these types
const sum: ConcatX<number> = (a, b) => a + b;
const product: ConcatY = (a: number, b: number) => a + b;

// Can define a function that takes a ConcatX
function DoMathX(sum: ConcatX<number>) {
  console.log(`1 + 1 is ${sum(1, 1)}`);
}

// But can't define a function that takes a ConcatY for numbers
// A and B are "unknown"
// Or is there a way?
function DoMathTwo(sum: ConcatY) {}

This:这:

type ConcatX<T> = (a: T, b: T) => T;

Is a generic type alias , which contains a function that uses the generic parameter.是泛型类型别名,其中包含使用泛型参数的函数。 The generic parameter this function uses is locked in once the type is resolved.一旦类型被解析,这个函数使用的泛型参数就会被锁定。 That can be handy when some type needs to set the type of your function.当某些类型需要设置函数的类型时,这会很方便。

For instance here:例如这里:

const sum: ConcatX<number> = (a, b) => a + b;

This says that, externally to this function, you declare that the arguments of this function are numbers.这表示,在此函数的外部,您声明此函数的参数是数字。

Note that this is not really part of the function type at all.请注意,这根本不是函数类型的一部分。 This approach isn't fundamentally different than something like:这种方法与以下方法没有根本区别:

type ContatX<T> = { sum(a: T, b: T): T, someValue: T }

The point being that the T is set outside the function entirely, and the function just picks that up to use.关键是T完全设置在函数之外,函数只是选择使用它。


This:这:

type ConcatY = <T>(a: T, b: T) => T;

Is a generic function .是一个泛型函数 The generic parameter is set when the function is called , and can be different each time it's called.泛型参数在调用函数时设置,每次调用时都可以不同。 And that parameter may be inferred from the type of the arguments a and b .并且可以从参数ab的类型推断该参数。

You cannot lock down T ahead of time here because T is decided when the function is called and no sooner .您不能在这里提前锁定T ,因为T是在调用函数时决定的,而不是更早

Which means there is no subtype of ConcatY that only takes numbers.这意味着没有只接受数字的ConcatY子类型。 To type guard against bad usage here you would instead check the return type:要在此处输入防止不良使用,您可以检查返回类型:

const resultStr: string = sum(1,2) // error: cannot assign number to string
const resultNum: num = sum('a','b') // error: cannot assign string to number

In both cases the function call is completely valid, but the result is not what the type system is expecting, so you get an error.在这两种情况下,函数调用都是完全有效的,但结果不是类型系统所期望的,因此您会收到错误消息。


If you want a specific subtype of concat where the arguments must be numbers, then you want the generic type ConcatX .如果您想要参数必须是数字的特定 concat 子类型,那么您需要通用类型ConcatX

But if your function could take lots of different arguments, and the return type depends on the type of those arguments, and you don't know exactly what types it will be called with ahead of time, then you want the generic function ContactY .但是,如果您的函数可以接受许多不同的参数,并且返回类型取决于这些参数的类型,并且您不知道提前调用它的确切类型,那么您需要通用函数ContactY

Which all means that if you want to:这一切都意味着,如果您想:

"to indicate that a function takes one of these with specific argument types" “指示一个函数采用其中一个具有特定参数类型”

Then you need to use ContactX with a generic parameter to create a function type with the T locked to whatever you want.然后您需要使用带有泛型参数的ContactX来创建一个函数类型,其中T锁定为您想要的任何内容。

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

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