javascript - TypeScript 中泛型的行为

标签 javascript typescript

想学一下TS,关注官方page .

我在 Generics章节

来自指南:

function identity(arg: any): any {
    return arg;
}

他们声明如下:

While using any is certainly generic in that it will cause the function to accept any and all types for the type of arg, we actually are losing the information about what that type was when the function returns. If we passed in a number, the only information we have is that any type could be returned.

现在让我们观察这段代码:

let whatIsMyType = identity(666);
typeof whatIsMyType; // number

我没有丢失类型信息。他们指的是什么样的损失?

进一步阅读,指南建议使用 T 类型,如下所示:

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

附说明:

We’ve now added a type variable T to the identity function. This T allows us to capture the type the user provides (e.g. number), so that we can use that information later. Here, we use T again as the return type. On inspection, we can now see the same type is used for the argument and the return type. This allows us to traffic that type information in one side of the function and out the other.

最后: TS 中的函数(具有任何类型的签名)

function identity(arg: any): any {
    return arg;
}

以及泛型类型 T 的函数:

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

}

一旦编译为纯 JS,它们看起来都是相同的:

function identity(arg) {
    return arg;
}

现在,我明白了预警的好处,我也明白了any签名。我不明白为什么说我丢失了类型,我应该使用 "T" 签名。

哪个更复杂,但基本相同。

最佳答案

Now lets observe this piece of code: let whatIsMyType = identity(666); typeof whatIsMyType; // number I have not lost type information. What kind of loss they refer to?

这是关于静态类型信息和运行时类型信息之间的区别。 TypeScript 是关于静态类型信息的——TypeScript 编译器可以使用这些信息来帮助您保持程序代码的正确性。但是 typeof (在这种情况下)是一个 JavaScript runtime operation 告诉你(用非常笼统的术语)当你使用 typeof 就可以了。

如果您将该代码粘贴到 the playground 并将鼠标悬停在 whatIsMyType 变量上,您将看到它的 TypeScript 类型为 any,这意味着您可以愉快地分配在调用identity之后将“foo”(或其他任何内容)添加到它:

function identity(arg: any): any {
    return arg;
}
let whatIsMyType = identity(666);
console.log(whatIsMyType);
whatIsMyType = "foo";          // No error here
console.log(whatIsMyType);

由于其类型为 any,因此该变量的类型类似于 JavaScript 变量。

TypeScript 的目标,即它存在的理由,是静态(编译时)类型检查。 any 类型是静态类型检查无用(甚至由于第三方集成而可能)的情况的逃生舱。 (这些情况确实存在,但很少见。)

once compiled to plain JS, they look both identical:

没错。 TypeScript 使用的静态类型信息不是最终输出的一部分。这是编译时的事情,而不是运行时的事情。 (枚举在运行时的存在量很小。)但是请注意,在编译时,使用泛型会如何改变事物 - 如果您运行此代码 in the playground :

function identity<T>(arg: T): T {
    return arg;
}
let whatIsMyType = identity(666);
console.log(whatIsMyType);
whatIsMyType = "foo";       // <== Error: Type '"foo"' is not assignable to type 'number'.
console.log(whatIsMyType);

...您可以看到将 "foo" 分配给 whatIsMyType 现在是一个编译时错误。


¹ “..typeof(在该上下文中)...” 有点令人困惑的是,还有一个 TypeScript typeof operator 可以在 type< 中使用/em> 上下文,它与 JavaScript 的运行时 typeof 关键字(在您的示例中使用)不同,后者在 value 上下文中使用。在 TypeScript 中,有些地方需要 类型(类型上下文),例如变量声明中的 : 之后:

let a: type_expected_here;

...以及其他需要的地方(值上下文),例如赋值的右侧:

a = value_expected_here;

如果您在类型上下文中使用typeof,则它是TypeScript的typeof运算符。例如,如果您有以下声明:

let foo: number = 42;

...您可以使用typeof bar声明一个与foo类型相同的变量,like this:

let a: typeof foo;

由于 typeof 的使用是预期 type 的地方,因此 a 将具有 number 类型,因为这就是 foo 的类型。如果您更改 foo 的声明,使其变为字符串,a 的类型也会随之更改。

相比之下:

let a = typeof foo;

其中,typeof 位于值上下文中,因此它是 JavaScript 的运行时 typeof 关键字,并且 a 将获取值(不是类型)"number"(在该特定示例中,a 的类型将被推断为 string,因为这是JavaScript 的 typeof 的结果始终是什么)。

一开始这看起来很困惑,但随着时间的推移会变得更加清晰。


请注意,以上所有内容都是从 TypeScript Angular 来看的。您认为静态类型检查是帮助还是障碍取决于您。 :-) 但为了这个答案,我假设从 TypeScript Angular 来看。

关于javascript - TypeScript 中泛型的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57711703/

相关文章:

javascript - Angular 惰性模块中的共享组件

javascript - 在Angular应用中使用ngx-monaco-editor在404结果

javascript - 如何使用javascript过滤功能

javascript - 带有固定导航栏的图像顶部的 HTML/CSS 图像

javascript - Typescript/Lodash group by——尝试将数组键的值与其数量分组

typescript - ionic2 中的导入指令 - ng2-qrcode

angular - 映射函数给出未解析的函数或方法(映射)

javascript - JavaScript 减少

javascript - 尝试在标记单击时从 JSON 检索值

javascript - 如何使用 HTML5 刮刮卡渲染随机背景