打字稿“泛型”语法+尖括号

时间:2020-08-21 03:32:04

标签: javascript typescript casting

我很难理解Typescript尖括号后面的目的。

通常,它们用于泛型。对我来说,这对于功能来说是最清楚的。例如,如果您要使某个函数具有更高的可重用性(或“泛型”),则可以在函数名称之后应用它们,如下所示:

function identity<T>(arg: T): T { 
    return arg; 
};

这可以增强类型安全性,同时还允许您将此函数用于多种类型。

但是,在其他情况下,<>括号在 其他类型之后出现,例如在以下事件处理程序中:

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
    const val = e.currentTarget.value;
    setWord(val);
  };

通过查看Typescript的自动完成功能,React.ChangeEvent会显示以下内容:React.ChangeEvent<Element>

  1. 在这种情况下,<Element>是什么意思?它也是通用的吗?
  2. 我们是否传入了HTMLInputElement,如果是,那是接口吗?
  3. 最后,为什么在这种情况下,泛型(如果正在发生这种情况)在React.ChangeEvent类型之后通过 传递,而对于函数,则传递了T泛型函数主体之前?

2 个答案:

答案 0 :(得分:2)

React.ChangeEvent<HTMLInputElement>语法显示所谓的Generic Type。此类型会收到另一种类型的“参数”,以进一步更好地指定它。

认为泛型类似于函数,只是类型。我们用来接收一个或多个值并产生另一个值的函数。泛型类型相似,它们接收一个或多个类型并产生一个类型。单独的泛型类型可能不足以表示某些东西,这取决于是否用可选参数声明了它(就像一个函数可能具有可选参数一样)。

这是一个通用类型简单得多的示例:Array<T>。这只是T[]的另一种说法。例如,Array<number>。另一个非常常见的泛型类型是Promise<T>,它表示解析为T的承诺的类型。

Promise是一个通用类型的好例子,其参数是必需的

// --------------------------------------
// | interface Promise<T>               |
// --------------------------------------
// | Represents the completion of an    |
// | asynchronous operation             |
// --------------------------------------
// | Generic type 'Promise<T>' requires |
// | 1 type argument(s).   ts(2314)     |
// --------------------------------------
//          ^
//          |
//          |
type X = Promise;

假设您要以{ foo: something }的形式表示一个对象,其中任何对象都可以是您想要的。您可以使用通用类型来做到这一点:

type Foo<SomeType> = {
  foo: SomeType;
};

// Now you can declare specific types

type FooWithString = Foo<string>;
// equivalent of:
// type FooWithString = { foo: string };

type FooWithNumber = Foo<number>;
// equivalent of:
// type FooWithString = { foo: number };

如果我们想将此SomeType设为可选的类型参数,以便我们的通用类型Foo也可以单独使用(无需通过尖括号传递类型),我们只需决定我们希望其默认类型是什么(类似于我们为普通功能选择默认值的方式):

type Foo<SomeType = Date> = {
  foo: SomeType;
};

现在我们可以在不使用尖括号的情况下使用Foo了-等同于进行Foo<Date>


您可以在TypeScript reference for Utility Types中找到一些有趣的类型示例。


明确回答您的问题:

1。<Element>显示您正在悬停的通用类型(即React.ChangeEvent)收到一个类型参数,而来自React团队的人创建了该通用类型决定将此参数称为Element

  • 在上面的示例中,如果您将鼠标悬停在Foo<number>上,它将显示Foo<SomeType>,因为这就是我声明类型的方式。

2a。是,我们将HTMLInputElement作为参数传递给通用类型React.ChangeEvent。将React.ChangeEvent看作是一个“类型函数”,它接受一个类型参数并“返回”另一个类型。因此,我们将HTMLInputElement赋予React.ChangeEvent,以便得到的类型React.ChangeEvent<HTMLInputElement>指定我们想要的内容。

2b。。是否作为界面无关紧要。 interface只是一种语法,用于声明与标准type Foo = /* ... */相比具有一些怪癖的类型。现在不用担心这些细节。

3。。这正是TypeScript开发人员确定语法的方式。例如,它与Java的语法相匹配,在Java中,我们具有诸如ArrayList<String>之类的通用类型和诸如myFunc<SomeType>(a: SomeType)之类的通用函数。

答案 1 :(得分:1)

ChangeEvent就像可以向函数传递类型一样,因此您正在向其中传递具体类型。您也可以将具体类型传递给函数-identity<MyType>(myArg),尽管您可能不需要,因为您可以从传递的参数中推断出类型,因为它们都共享T

区别在于ChangeEvent不能从参数推断类型,因为它不是函数,因此您需要显式为其指定一个。

HTMLInputElement可以是typeinterfaceChangeEvent会因HTML元素类型的不同而有所不同(对input的更改与对select的更改不同),因此您传入了要获取的元素类型完成最后的界面。