Typescript 类型推断
TypeScript 能根据一些简单的规则推断(检查)变量的类型,你可以通过实践,很快的了解它们。
#定义变量
变量的类型,由定义推断:
`let foo = 123; // foo 是 'number' let bar = 'hello'; // bar 是 'string'
foo = bar; // Error: 不能将 'string' 赋值给 `number``
这是一个从右向左流动类型的示例。
#函数返回类型
返回类型能被 return
语句推断,如下所示,推断函数返回为一个数字:
function add(a: number, b: number) { return a + b; }
这是一个从底部流出类型的例子。
#赋值
函数参数类型/返回值也能通过赋值来推断。如下所示,foo
的类型是 Adder
,他能让 foo
的参数 a
、b
是 number
类型。
type Adder = (a: number, b: number) => number; let foo: Adder = (a, b) => a + b;
这个事实可以用下面的代码来证明,TypeScript 会发出正如你期望发出的错误警告:
type Adder = (a: number, b: number) => number; let foo: Adder = (a, b) => { a = 'hello'; // Error:不能把 'string' 类型赋值给 'number' 类型 return a + b; };
这是一个从左向右流动类型的示例。
如果你创建一个函数,并且函数参数为一个回调函数,相同的赋值规则也适用于它。从 argument
至 parameter
只是变量赋值的另一种形式。
`type Adder = (a: number, b: number) => number; function iTakeAnAdder(adder: Adder) { return adder(1, 2); }
iTakeAnAdder((a, b) => { a = 'hello'; // Error: 不能把 'string' 类型赋值给 'number' 类型 return a + b; });`
#结构化
这些简单的规则也适用于结构化的存在(对象字面量),例如在下面这种情况下 foo
的类型被推断为 { a: number, b: number }
:
`const foo = { a: 123, b: 456 };
foo.a = 'hello'; // Error:不能把 'string' 类型赋值给 'number' 类型`
数组也一样:
const bar = [1, 2, 3]; bar[0] = 'hello'; // Error:不能把 'string' 类型赋值给 'number' 类型
#解构
这些也适用于解构中:
`const foo = { a: 123, b: 456 }; let { a } = foo;
a = 'hello'; // Error:不能把 'string' 类型赋值给 'number' 类型`
数组中:
`const bar = [1, 2]; let [a, b] = bar;
a = 'hello'; // Error:不能把 'string' 类型赋值给 'number' 类型`
如果函数参数能够被推断出来,那么解构亦是如此。在如下例子中,函数参数能够被解构为 a/b
成员:
`type Adder = (number: { a: number; b: number }) => number; function iTakeAnAdder(adder: Adder) { return adder({ a: 1, b: 2 }); }
iTakeAnAdder(({ a, b }) => { // a, b 的类型能被推断出来 a = 'hello'; // Error:不能把 'string' 类型赋值给 'number' 类型 return a + b; });`
#类型保护
在前面章节**类型保护**中,我们已经知道它如何帮助我们改变和缩小类型范围(特别是在联合类型下)。类型保护只是一个块中变量另一种推断形式。
#警告
#小心使用参数
如果类型不能被赋值推断出来,类型也将不会流入函数参数中。例如如下的一个例子,编译器并不知道 foo
的类型,所它也就不能推断出 a
或者 b
的类型。
const foo = (a, b) => { /* do something */ };
然而,如果 foo
添加了类型注解,函数参数也就能被推断(a
,b
都能被推断为 number
类型):
type TwoNumberFunction = (a: number, b: number) => void; const foo: TwoNumberFunction = (a, b) => { /* do something */ };
#小心使用返回值
尽管 TypeScript 一般情况下能推断函数的返回值,但是它可能并不是你想要的。例如如下的 foo
函数,它的返回值为 any
:
`function foo(a: number, b: number) { return a + addOne(b); }
// 一些使用 JavaScript 库的特殊函数 function addOne(a) { return a + 1; }`
这是因为返回值的类型被一个缺少类型定义的 addOne
函数所影响(a
是 any
,所以 addOne
返回值为 any
,foo
的返回值是也是 any
)。
TIP
我发现最简单的方式是明确的写上函数返回值,毕竟这些注解是一个定理,而函数是注解的一个证据。
这里还有一些其他可以想象的情景,但是有一个好消息是有编译器选项 noImplicitAny
可以捕获这些 bug。
#noImplicitAny
选项 noImplicitAny
用来告诉编译器,当无法推断一个变量时发出一个错误(或者只能推断为一个隐式的 any
类型),你可以:
- 通过显式添加
:any
的类型注解,来让它成为一个any
类型; - 通过一些更正确的类型注解来帮助 TypeScript 推断类型。
Typescript 类型推断相关推荐
- TypeScript Type Innference(类型推断)
在这一节,我们将介绍TypeScript中的类型推断.我们将会讨论类型推断需要在何处用到以及如何推断. 基础 在TypeScript中,在几个没有明确指定类型注释的地方将会使用类型推断来提供类型信息. ...
- TypeScript类型检查机制
类型推断 指不需要指定变量的类型,TS编译器可以根据某些规则自动推断出类型. 什么时候会有类型推断? 声明变量时没有指定类型 函数默认参数 函数返回值 ...... let a; // 这时自动推断为 ...
- typeScript类型学习
typeScript类型学习 1. 字面量 1.1 什么是字面量 1.2 为什么要有字面量 1.3 ts中的字面量 2.|(联合类型) 3.any 4.unknown 5.unknown和any的区别 ...
- 【TypeScript】(一)快速上手TypeScript类型语法
文章目录 1.概述 2.TS中的类型 2.1.类型推断 2.2.类型定义 2.3.复杂类型 2.3.1.联合 2.3.2.泛型 2.4.type关键字 3. 总结 1.概述 TypeScript(TS ...
- Javascript类型推断(1) - 获取token和类型
Javascript类型推断(1) - 获取token和类型 js类型推断的三种思路 第一种思路是用传统的编译类的方法,推断是没啥好办法,但是可以用来验证. 第二种思路是利用对象的属性或方法的调用来推 ...
- Java 8新特性探究(6):泛型的目标类型推断
简单理解泛型 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数.通俗点将就是"类型的变量".这种类型变量可以用在类.接口和方法 ...
- 【Groovy】Groovy 动态语言特性 ( Groovy 中函数实参自动类型推断 | 函数动态参数注意事项 )
文章目录 前言 一.Groovy 中函数实参自动类型推断 二.函数动态参数注意事项 三.完整代码示例 前言 Groovy 是动态语言 , Java 是静态语言 ; 本篇博客讨论 Groovy 中 , ...
- 【Groovy】Groovy 动态语言特性 ( Groovy 中的变量自动类型推断以及动态调用 | Java 中必须为变量指定其类型 )
文章目录 前言 一.Groovy 动态语言 二.Groovy 中的变量自动类型推断及动态调用 三.Java 中必须为变量指定其类型 前言 Groovy 是动态语言 , Java 是静态语言 ; 一.G ...
- auto自动类型推断
文章目录 1 auto 1 auto auto在C++11之前是自动变量的含义(栈变量,局部变量),在C++11后赋予其新的作用:自动类型推断. auto可以在声明变量的时候根据初始值的类型自动为此变 ...
最新文章
- 计算机四级网络工程师考试重点
- python路径拼接问题
- 漫谈设计模式--3分钟理解桥接模式:笔和画的关系
- mysql 客户端_技术分享 | MySQL 客户端连不上(1045 错误)原因全解析
- 在对比了 GitHub 5000 个 Python 项目之后,我们精选出了这 36 个!
- 关于10g RAC监听设置,tnsnames.ora设置,VIP及客户端配置问题
- 当字段过长,鼠标移上去才展示全部,默认只展示部分防止表格比例发生变化
- 图书管理系统~简单流程
- 通过#define连接字符串的特殊方法[转]
- php实现凯撒密码加密算法,Python实现的凯撒密码算法示例
- 华东师范大学计算机模拟试题,华东师范大学网院《计算机入门》模拟试题(卷)(ABCD卷合,含详细答案解析).doc...
- Java基础篇:如何应用接口?
- 二十一天学通C++之使用throw抛出异常
- 精品软件介绍 Wireless Network Watcher 中文版 - 防蹭网监视软件
- 优启通制作系统u盘_如何用优启通制作U盘启动盘
- QTransform(图形平移旋转剪切变换)
- C++输入日期判断是周几
- MATLAB在动态经济学中的应用,MATLAB在动态经济学中的应用
- 【python入门篇——11】字典(dict)详解
- 阿里云BaaS下蚂蚁区块链开发实践(二)