TypeScript
2018-11-05 14:18:35 0 举报
AI智能生成
TypeScript语法
作者其他创作
大纲/内容
官网
official site
official site
英文官网
中文官网
有少量错误,请参照英文版
本文结构来自于中文官网
GitHub
语言规范
核心原则
core principles
core principles
对值所具有的结构进行类型检查。
它有时被称做
鸭式辨型法
duck typing
duck typing
或 结构性子类型化
structural subtyping
structural subtyping
另一个解读:“不把类型检查带到runtime”
手册
Handbook
Handbook
基础
标识符
标识符可以包括下划线,字符和数字。标识符不能以数字开头
标识符不能是关键字
标识符必须是唯一的
标识符是区分大小写
分隔符
语句结束符号分号是可选的
注释
单行 //
多行 /* */
关键字
基础类型
Basic Types
Basic Types
boolean
number
浮点数
string
普通字符串
" "
模板字符串
` ${ }`
反引号是标准键盘数字键1左边的波浪号键
类似于C#的格式化字符串
示例
Array 数组
数组 []
示例
多维数组[][]
示例
泛型数组 Array<T>
示例
泛型只读数组 ReadonlyArray<T>
示例
数组的排序
sort 与c#用法相同
示例
数组的删除
注意Array没有remove方法,使用splice替代
注意splice的第二个参数,一般情况下需要手动填1,否则意味着删除之后所有元素
示例
Tuple 元组
一个已知元素数量和类型的数组,各元素的类型不必相同
示例
当访问一个越界的元素,会使用联合类型替代
示例
Tuple和struct的区别是什么?
enum
enum 示例
默认从0开始编号
any
动态类型,会跳过编译器检查
这意味着any数据可以调用任何属性/方法而编译不报错
(哪怕这些属性/方法不存在),直到运行时才会报错
(哪怕这些属性/方法不存在),直到运行时才会报错
引入这个类型的原因就是为了打破自己的核心原则么?
与Object的区别
Any可以调用任意实例的方法
Object只能调用Object的方法
void
用于函数表示没有返回值
可以被赋值 null 和 undefined
null
默认情况下null和undefined是所有类型的子类型
如果指定了strictNullChecks,null只能赋值给null类型
undefined
默认情况下null和undefined是所有类型的子类型
如果指定了strictNullChecks,undefined只能赋值给undefined类型
never
never类型表示的是那些永不存在的值的类型
例如, never类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型
never类型是任何类型的子类型,也可以赋值给任何类型
只有never才能赋值给never,any不可以赋值给never
Object
object表示非原始类型,也就是除number,string,boolean,symbol,null或undefined之外的类型
类型断言
跳过编译,但不影响运行
<> 语法
示例
as 语法
示例
as与<>是等价的
特例:当使用JSX时只能使用as
变量声明
Variable Declarations
Variable Declarations
命名规则
遵循JS的命名规则
可以包含字母,数字,下划线 和 $
不能包含空格和特殊字符
不能以数字开头
特殊的$
由于JQuery广泛运用,一般单独的$是指jQuery
ES3 曾建议将$开头的命名用于自动生成的代码
var 声明
请使用let替换var
作用域
详见js章节
let 声明
请使用let替换var
作用域
词法作用域(或块作用域)
示例1 if 块
示例2 try catch 块
不能在被声明之前读或写
示例
但可以在被声明前获取它 (仅仅是写法上的)
示例
const 声明
注意内部值是可以修改的
不可用于类成员的修饰符
类中如何定义常量?参见接口章节
对比
let VS const
不应修改的量仍然使用const
readonly vs const
做为变量使用的话用 const,若做为属性则使用readonly。
解构 Destructuring
数组解构[]
常规用法
示例
交换
示例
函数参数
示例
剩余变量
示例
忽略部分变量
忽略尾部变量
忽略部分变量
默认值
示例
对象解构{}
提取属性值
示例
强制类型
示例
剩余变量(剩余对象?)
示例
属性重命名
let { a: x, b: y } = o;
等价于 x=o.a y=o.b
等价于 x=o.a y=o.b
为什么要引入这个语法??
注意此处冒号后跟随的不是类型而是新变量名字
此处似乎无法强制类型
默认值
示例
函数声明{}
简单情况
示例
复杂情况
首先需要在默认值之前设置其格式
示例
其次需要知道在解构属性上给予一个默认或可选的属性用来替换主初始化列表。
示例
注意
要小心使用解构
避免在深层嵌套中解构
解构表达式要保持小而简单
展开(Spread) ...
将数组展开为另一个数组
示例
展开创建了一份浅拷贝
将对象展开为另一个对象
注意展开顺序是从左到右的,
如果右侧与左侧有相同的属性,会被右侧的属性覆盖
如果右侧与左侧有相同的属性,会被右侧的属性覆盖
示例
对象展开仅包含自身的直接属性和可枚举属性
原文是 own,enumerable properties
Enumerable properties 枚举属性
Ownership of properties
这个涉及到js里的prototype的概念,尚不理解
此句可简单理解为扩展对象会丢失方法
暂不允许展开泛型函数上的类型参数
接口
Interfaces
Interfaces
属性
简单示例
我们在这里并不能像在其它语言里一样,说传给 printLabel的对象实现了这个接口。
我们只会去关注值的外形。(Here, it’s only the shape that matters.)
只要传入的对象满足上面提到的必要条件,那么它就是被允许的。
我们只会去关注值的外形。(Here, it’s only the shape that matters.)
只要传入的对象满足上面提到的必要条件,那么它就是被允许的。
这里shape翻译为“外形”似乎有点奇怪?
可选属性?
可选属性在应用“option bags”模式时很常用,即给函数传入的参数对象中只有部分属性赋值
示例
好处1 对可能存在的属性进行预定义
好处2 可以捕获引用了不存在的属性时的错误
比如故意将color属性名字拼写错误
只读属性
示例
个人看法这个段落应归到“基本类型”中
只读数组
ReadonlyArray<T>
个人看法这个段落应归到“基本类型”中
示例
额外的属性检查
检查对象是否存在任何“目标类型”不包含的属性
可以避免拼写错误
示例 拼写错误
在JavaScript里,这样写是允许的(但不能正确赋值)
TypeScript会认为这段代码可能存在bug并报错
如何绕开此限定
方法1 断言
示例
方法2 向接口中添加索引签名(推荐)
示例
方法3 将对象赋值给另一个对象
示例
没理解为什么会绕过检查?
函数类型
Function Types
Function Types
这里的用法与以上几种都不同
为了使用接口表示函数类型,我们需要给接口定义一个调用签名。
示例
函数的参数名不需要与接口里定义的名字相匹配
示例
可以省略类型,让编辑器做类型推断
这个用法的意义是什么?提供比类的灵活性更高的一种用法?
索引类型
Indexable Types
Indexable Types
定义索引签名
示例
支持两种索引签名
字符串
注意字符串索引签名会强制要求所有属性返回值与字符串索引返回值相同
因为obj.property会被当作obj["property"]执行
示例
这段翻译有问题,推荐看英文版本理解
数字
可以同时使用,
但是数字索引的返回值必须是字符串索引返回值类型的子类型。
但是数字索引的返回值必须是字符串索引返回值类型的子类型。
这是因为当使用 number来索引时,JavaScript会将它转换成string然后再去索引对象。
也就是说用 100(一个number)去索引等同于使用"100"(一个string)去索引,因此两者需要保持一致。
也就是说用 100(一个number)去索引等同于使用"100"(一个string)去索引,因此两者需要保持一致。
示例
将索引设为只读
示例
类类型
Class Types
Class Types
可用于描述公共属性和方法
属性示例
方法示例
类静态部分与实例部分的区别
接口仅描述实例部分
如果需要描述构造器(静态部分)
可以考虑不直接继承,而是用检查的方式
可以考虑不直接继承,而是用检查的方式
示例
继承接口
Extending Interfaces
Extending Interfaces
单继承
示例
多继承
简单情况示例
如果不同父接口中有相同的属性声明
定义完全相同,可以多继承
示例
定义不同,不可多继承
上例中,如果color的类型不同会报错
混合类型
Hybrid Types
Hybrid Types
一个对象可以同时做为函数和对象使用,并带有额外的属性。
示例
接口继承类
Interfaces Extending Classes
Interfaces Extending Classes
当接口继承了一个类类型时,它会继承类的成员但不包括其实现。
接口同样会继承到类的private和protected成员。
这意味着当你创建了一个接口继承了一个拥有私有或受保护的成员的类时
这个接口类型只能被这个类或其子类所实现
这个接口类型只能被这个类或其子类所实现
示例
类
class
class
示例
构造器
constructor
this
在类的内部引用任何一个类成员的时候都用了 this,表示引用的是类成员
继承
示例
派生类的构造函数必须调用 super()
在构造函数里访问 this的属性之前,一定要调用 super()
重写
不需要override修饰符,可以调用super
不允许多继承
很意外?需要深入了解TS的混入机制
交叉类型是一种解决方式
公共,私有与受保护的修饰符
public
属性方法都默认为public
private
private不可在外部调用
示例
private不可重写
示例
protected
protected 不可在外部调用
示例
注意protected是可继承的,
子类中的重写可以是public
子类中的重写可以是public
示例
兼容性问题
示例
readonly 声明
允许在类的构造函数中赋值
示例
static readonly
不允许在类构造中赋值,仅能在定义处赋值
参数属性
把声明和赋值合并至一处
示例
有啥好处???
存取器
get / set
示例
简略写法
存取器要求你将编译器设置为输出ECMAScript 5或更高。
只带有 get不带有 set的存取器自动被推断为 readonly。
静态属性
static
示例
即便是在类内部要访问这个属性的时候,都要写作 类名.属性名
抽象类
abstract
高级技巧
构造函数
把类当做接口使用
接口一章的“接口继承类”
函数
Functions
Functions
函数
普通函数
示例
匿名函数
示例
捕获外部变量
示例
函数类型
函数类型包含两部分
参数类型
返回值类型
在完整函数类型写法中,
在函数和返回值类型之间使用( =>)符号
在函数和返回值类型之间使用( =>)符号
为函数定义类型
示例
书写完整函数类型
示例
参数名只是为了可读性,可以不统一
示例
无返回值的情况下void不可省略
用在哪里的
类型定义
接口
推断类型
编译器会按上下文归类,推断类型
可选参数和默认参数
编译器检查用户是否为每个参数都传入了值
示例
传入更多值也是不允许的
示例
可不传值的情况
可选参数
示例
可选参数应放在必须参数后面
默认参数
示例
默认参数是可选参数
带默认值的参数可以出现在必须参数前面,
此时只有在明确的传入 undefined值时才会获得默认值。
此时只有在明确的传入 undefined值时才会获得默认值。
剩余参数
示例
可以用在完整函数类型定义上
示例
this
JavaScript中,this的值只在函数被调用时才会指定
理解this原理
this与function函数
示例
运行会报错
顶级的非方法式调用会将 this视为window。
(注意:在严格模式下, this为undefined而不是window)。
(注意:在严格模式下, this为undefined而不是window)。
如果编译器设置了--noImplicitThis
那么在使用function()的地方会有错误警告
那么在使用function()的地方会有错误警告
示例
this和箭头函数
箭头函数能保存函数创建时的 this值
而不是调用时的值
而不是调用时的值
示例
在VS中,用鼠标放在this上还可以看到类型提示
this 参数
显式的this参数可以令this在调用时的类型不为any
示例
--noImplicitThis不会报错
注:此处可能是文档未更新导致的问题
实测在VS中不写this参数,严格模式也不会报错,可以正常运行
实测在VS中不写this参数,严格模式也不会报错,可以正常运行
this参数 应在参数表的第一位
this参数在回调函数中
当回调被调用的时候,会被当成一个普通函数调用
在回调方法中的this将为undefined。
在回调方法中的this将为undefined。
利用this避免错误
没看懂
重载
注意TS重载的实现是与静态语言不同的!
原文中并没有强调如下格式
原文中并没有强调如下格式
首先要声明重载函数,仅声明!
声明时要注意顺序,在重载时是按照顺序来查找对应的!
然后要写出重载的具体实现(没错,需要自己实现!)
示例1 单参数
示例2 多参数
示例3 可选参数
泛型
Generics
Generics
泛型定义
概念与C#基本相同
泛型变量
概念与C#基本相同
泛型类型
示例
泛型类
示例
泛型约束
extends
示例
在泛型约束中使用类型参数
示例
注意此处中文翻译有误,请参看英文版
在泛型里使用类类型
在TypeScript使用泛型创建工厂函数时
需要引用构造函数的类类型。
需要引用构造函数的类类型。
示例
使用原型属性推断并约束构造函数与类实例的关系
示例
枚举
Enums
Enums
数字枚举
默认从0开始
允许值重复
示例
容易混淆的地方
允许枚举值重复的语言
C++
C#
ObjectC
python
两个相同值的成员,第二个成员的名称被视作第一个成员的别名
不允许枚举值重复的语言
Java
通过自定义构造函数可以达到重复的效果
允许用表达式赋值
常量表格式
非常量表达式
原文说法:不被初始化的枚举要么放在第一位,要么放在其他被常量初始化过的枚举之后
换个说法:必须对对非常量表格式之后的每一个枚举赋值,不可省略
举例
反向映射
示例
重复的值会被替代
示例
多个声明
示例
会自动合并为一个枚举
不可重复
示例
只有一个声明可以省略第一个枚举元素的初始化表达式
示例
很容易重复
示例
字符串枚举
必须用字符串字面量,或另外一个字符串枚举成员进行初始化
不支持反向映射
允许重复
允许多个声明
异构枚举
Heterogeneous enums
Heterogeneous enums
混合字符串和数字成员
示例
非特殊情况不推荐使用
计算的和常量成员
当满足如下条件之一时,枚举成员被当作是常量:
它是枚举的第一个成员且没有初始化器,这种情况下它被赋予值 0:
示例
它不带有初始化器且它之前的枚举成员是一个 数字常量。
示例
枚举成员使用 常量枚举表达式初始化。
常数枚举表达式指可以在编译阶段求值的表达式。
示例
否则为计算量
联合枚举与枚举成员的类型
Union enums and enum member types
Union enums and enum member types
字面量枚举成员
literal enum members
literal enum members
不带有初始值的常量枚举成员
值被初始化为任何字符串的字面量
值被初始化为任何数字字面量
值被初始化为应用了一元运算符的数字字面量(例如负号)
当所有枚举成员都拥有字面量枚举值时
枚举成员成为了类型
可用于定义变量类型
示例
枚举类型本身变成了每个枚举成员的 联合
运行时的枚举
枚举是在运行时真正存在的对象,可当作实例化的对象使用
const枚举
const enum
常量枚举只能使用常量枚举表达式
不同于常规的枚举,它们在编译阶段会被删除。
常量枚举成员在使用的地方会被内联进来。
常量枚举成员在使用的地方会被内联进来。
示例
外部枚举
declare enum
在正常的枚举里,没有初始化方法的成员被当成常数成员。
对于非常数的外部枚举而言,没有初始化方法时被当做需要经过计算的
对于非常数的外部枚举而言,没有初始化方法时被当做需要经过计算的
外部枚举并不直接生成代码,直接引用外部枚举值会报undefined,外部枚举用于第三方库等情况
几种枚举的区别
enum
会生成代码
示例
const enum
生成内联代码
示例
declare enum
不生成相关代码
示例
declare const enum
生成内联代码
示例
枚举的遍历
示例
说明
直接遍历枚举会获得数字和表达式
遍历需要过滤
可以参与位运算
枚举与其他类型的转化
数字/字符串 和 枚举是通用的
示例
类型推论
Type Inference
Type Inference
基础
在省略类型时,编译器会推断类型
最佳通用类型
Best common type
Best common type
当需要在几个表达式中推断类型时,会使用这些表达式的类型来推断最佳通用类型
如果无法推断,则使用联合类型
上下文类型
Contextual Type
Contextual Type
类型兼容性
Type Compatibility
Type Compatibility
介绍
TypeScript里的类型兼容性是基于
结构子类型的(structural subtyping)。
结构子类型的(structural subtyping)。
示例
结构类型
Structural typing
Structural typing
C#
Java
...
名义类型
nominal typing
nominal typing
JS / TS
Lua
...
数据类型的兼容性或等价性是通过明确的声明和/或类型的名称来决定
关于可靠性的注意事项
比较原始类型和对象类型
如果x要兼容y,那么y至少具有与x相同的属性
示例
检查函数参数时使用相同的规则
示例
比较两个函数
参数
要查看x是否能赋值给y,首先看它们的参数列表。
x的每个参数必须能在y里找到对应类型的参数。
x的每个参数必须能在y里找到对应类型的参数。
示例
允许忽略参数
返回值
源函数的返回值类型必须是
目标函数返回值类型的子类型
目标函数返回值类型的子类型
示例
函数参数双向协变
Function Parameter Bivariance
Function Parameter Bivariance
只有当源函数参数能够赋值给目标函数
或者反过来时才能赋值成功
或者反过来时才能赋值成功
???
可选参数及剩余参数
Optional Parameters and Rest Parameters
Optional Parameters and Rest Parameters
???
函数重载
有点反认知,仔细看例子
枚举
示例
枚举类型与数字类型兼容,并且数字类型与枚举类型兼容。
不同枚举类型之间是不兼容的。
类
比较两个类类型的对象时,只有实例的成员会被比较。
静态成员和构造函数不在比较的范围内。
静态成员和构造函数不在比较的范围内。
示例
类的私有成员和受保护成员
在类章节有相关内容
泛型
泛型参数仅在被当作成员类型时才被比较
示例1 不作为成员类型
示例2 作为成员类型
对于没指定泛型类型的泛型参数时,会把所有泛型参数当成any比较。
示例
高级主题
子类型
赋值
高级类型
Advanced Types
Advanced Types
交叉类型 &
Intersection Types
Intersection Types
定义:交叉类型是将多个类型合并为一个类型,
它包含了所需的所有类型的特性。
它包含了所需的所有类型的特性。
示例
这个示例是错误的
可以通过编译的原因是交叉类型的定义正确
错误原因是没有对result的log方法赋值
使用for...in...仅遍历的属性而没有遍历方法
使用for...in...仅遍历的属性而没有遍历方法
正常用法
个人感觉就是多继承
属性名相同但类型不同
错误用法
不要对基础类型做交叉
正确用法
注意到同名属性做了交叉而不是覆盖
因此可以得到交换律
因此可以得到交换律
这个特点与展开(Spread)不同,展开会覆盖
交换律
X&Y 和 Y&X 是兼容的
联合类型 |
Union Types
Union Types
定义:联合类型表示一个值可以是几种类型之一
示例
只能访问联合类型的所有类型里共有的成员。
类型保护与区分类型
Type Guards and Differentiating Types
Type Guards and Differentiating Types
断言
用户自定义类型保护
示例
上例中,pet is Fish就是类型谓词。
谓词为 parameterName is Type这种形式,
parameterName必须是来自于当前函数签名里的一个参数名。
谓词为 parameterName is Type这种形式,
parameterName必须是来自于当前函数签名里的一个参数名。
TypeScript不仅知道在 if分支里 pet是 Fish类型;
它还清楚在 else分支里,一定 不是 Fish类型,一定是 Bird类型。
它还清楚在 else分支里,一定 不是 Fish类型,一定是 Bird类型。
typeof 类型保护
示例
限制1:语法限定
typeof v === "typename"
typeof v !== "typename"
限制2:typename限定
"number"
"string"
"boolean"
"symbol"
除以上四个类型外的字符串不被视为类型保护
instanceof类型保护
示例
限定:instanceof右侧必须是一个构造函数
之后的部分没看懂
可以为null的类型
Nullable types
Nullable types
默认null和undefined是所有类型的子类
strictNullChecks 可以避免null和undefined自动成为子类
可选参数和可选属性
使用了 --strictNullChecks,
可选参数/属性会被自动地加上 | undefined:
可选参数/属性会被自动地加上 | undefined:
可选参数示例
可选属性示例
类型保护和类型断言
目标:在联合类型中去除null
类型保护
类型断言 !
类型别名
Type Aliases
Type Aliases
示例
别名不会新建一个类型
与接口不同
类型别名也可以是泛型
示例
类型别名可以在属性里引用自己
示例
类型别名不能出现在声明右侧的任何地方。
示例
注意与上一条“可以在属性里引用自己”的区别
接口 vs. 类型别名
接口创建了一个新的名字,
类型别名并不创建新名字
类型别名并不创建新名字
类型别名不能被 extends和 implements
(自己也不能 extends和 implements其它类型)
(自己也不能 extends和 implements其它类型)
字符串字面量类型
String Literal Types
String Literal Types
可以实现类似枚举类型的字符串
示例
区分函数重载
示例
数字字面量类型
Numeric Literal Types
Numeric Literal Types
枚举成员类型
Enum Member Types
Enum Member Types
可辨识联合
Discriminated Unions
Discriminated Unions
合并单例类型,联合类型,类型保护和类型别名
来创建一个叫做 可辨识联合的高级模式,
它也称做 标签联合或 代数数据类型。
来创建一个叫做 可辨识联合的高级模式,
它也称做 标签联合或 代数数据类型。
具有普通的单例类型属性— 可辨识的特征。
一个类型别名包含了那些类型的联合— 联合。
此属性上的类型保护。
示例
完整性检查
方法1 启动strictNullChecks并且指定一个返回值类型
示例
方法2 使用never
示例
多态的 this类型
Polymorphic this types
Polymorphic this types
定义:多态的 this类型表示的是某个包含类或接口的 子类型。
这被称做 F-bounded多态性。
这被称做 F-bounded多态性。
示例
索引类型
Index types
Index types
使用索引类型,编译器就能够检查使用了动态属性名的代码
索引类型查询 操作符 keyof
index type query operator.
index type query operator.
对于任何类型 T, keyof T的结果为 T上已知的公共属性名的联合。
示例
索引类型访问 操作符 T[K]
indexed access operator
indexed access operator
示例
索引类型和字符串索引签名
示例
映射类型
Mapped types
Mapped types
没看懂
Symbols
自ECMAScript 2015起,symbol成为了一种新的原生类型,就像number和string一样。
symbol类型的值是通过Symbol构造函数创建的。
Symbols是不可改变且唯一的。
像字符串一样,symbols也可以被用做对象属性的键。
Symbols也可以与计算出的属性名声明相结合来声明对象的属性和类成员。
内置symbols
内置symbols用来表示语言内部的行为???
没看懂
迭代器和生成器
Iterators and Generators
Iterators and Generators
可迭代性
当一个对象实现了Symbol.iterator属性时,我们认为它是可迭代的
for of/in 的区别
迭代对象不同
for ... of
迭代的是对象的 键 的列表
for ... in
迭代对象的键对应的值
区别示例
操作对象不同
for ... in
可以操作任何对象
for ... of
关注于迭代对象的值
区别示例
命名空间
namespace
namespace
其定义和其他语言是一样的,区别就是需要public的成员修饰符为 export
单文件示例
分离到多文件
使用引用标签表示关联
示例
确保所有编译后的代码都被加载
方法1,把所有的输入文件编译为一个输出文件
示例
方法2,页面上通过 <script>标签顺序引入JavaScript文件
示例
别名
Aliases
Aliases
形如 import q = x.y.z
示例
使用其他的JS库
外部命名空间
模块
modules
modules
建议在看模块之前先看命名空间,原文应该是写反了顺序
定义:个人理解就是文件级的namespace
导出
导出声明 export
示例
导出语句
用于重命名
示例
重新导出
用于扩展其它模块
示例
导出多模块
示例
导入
导入一个模块中的某个导出内容
导入示例
导入重命名示例
将整个模块导入到一个变量,并通过它来访问模块的导出部分
示例
具有副作用的导入模块
默认导出
限定:每个模块最多只能有一个default导出
示例
类和函数声明可以直接被标记为默认导出
标记为默认导出的类和函数的名字是可以省略的。
标记为默认导出的类和函数的名字是可以省略的。
默认导出类示例
默认导出函数示例
default导出也可以是一个值
示例
export = 和
import = require()
import = require()
没看懂
export =语法定义一个模块的导出对象
若使用export =导出一个模块,
则必须使用TypeScript的特定语法
import module = require("module")来导入此模块。
则必须使用TypeScript的特定语法
import module = require("module")来导入此模块。
示例
生成模块代码
没看懂
可选的模块加载和其它高级加载场景
使用其它的JavaScript库
外部模块
外部模块简写
模块声明通配符
创建模块结构指导
导出
尽可能地在顶层导出
如果仅导出单个 class 或 function,使用 export default
如果要导出多个对象,把它们放在顶层里导出
导入
明确地列出导入的名字
使用命名空间导入模式当你要导出大量内容的时候
使用重新导出进行扩展
命名空间和模块
Namespaces and Modules
Namespaces and Modules
使用命名空间
使用模块
命名空间和模块的陷阱
别对模块使用 ///<reference> 这是namespace用的
不必要的命名空间
模块的取舍
模块解析
Module Resolution
Module Resolution
基础知识
定义:模块解析是指编译器在查找导入模块内容时所遵循的流程
定位策略: classic 或 Node
如果定位失败,且模块名是非相对的,
编辑器会尝试定位一个外部模块声明
编辑器会尝试定位一个外部模块声明
如果外部声明也找不到,那么报错
相对 vs. 非相对模块导入
相对导入
以 / ./ ../ 开头
示例
自己写的模块应该是使用相对导入
非相对导入
非以上格式的皆为非相对导入
示例
可以相对于baseUrl或者通过路径映射来解析
或者被解析为外部模块
模块解析策略
Classic
相对导入的模块是相对于导入它的文件进行解析的。
示例
非相对导入的模块从包含导入文件的目录开始依次向上级目录遍历
示例
Node
NodeJS如何解析模块
相对路径
示例
非相对路径
示例
TypeScript如何解析模块
模仿NodeJS
增加TypeScript源文件的扩展名( .ts,.tsx和.d.ts)
TypeScript在 package.json里使用字段"types"来表示类似"main"的意义
相对路径示例
非相对路径示例
附加的模块解析标记
工程源码结构与输出结构不同可能会打乱源文件路径关系
TS用一些额外的标记记录此过程中都发生了哪些转换。
TS用一些额外的标记记录此过程中都发生了哪些转换。
Base URL
在运行时模块都被放到了一个文件夹里
设置baseUrl来告诉编译器到哪里去查找模块。
所有非相对模块导入都会被当做相对于 baseUrl。
baseUrl的值由以下两者之一决定:
命令行中baseUrl的值(如果给定的路径是相对的,那么将相对于当前路径进行计算)
‘tsconfig.json’里的baseUrl属性(如果给定的路径是相对的,那么将相对于‘tsconfig.json’路径进行计算)
路径映射
有时模块不是直接放在baseUrl下面
TS通过使用tsconfig.json文件里的"paths"来支持这样的声明映射。
示例
通过"paths"我们还可以指定复杂的映射,包括指定多个回退位置。
示例
利用rootDirs指定虚拟目录
跟踪模块解析
使用--noResolve
常见问题
可以通过moduleResolution来标记指定策略
声明合并
Declaration Merging
Declaration Merging
定义
编译器将针对同一个名字的两个独立声明合并为单一声明。
合并后的声明同时拥有原先两个声明的特性。
任何数量的声明都可被合并;不局限于两个声明。
合并接口
示例
接口的非函数的成员应该是唯一的。
如果它们不是唯一的,那么它们必须是相同的类型。
如果两个接口中同时声明了同名的非函数成员且它们的类型不同,则编译器会报错。
如果它们不是唯一的,那么它们必须是相同的类型。
如果两个接口中同时声明了同名的非函数成员且它们的类型不同,则编译器会报错。
当接口 A与后来的接口 A合并时,后面的接口具有更高的优先级。
示例
优先级特例
签名里有一个参数的类型是单一的字符串字面量
示例
优先级的意义是什么?实现接口时并不在意顺序啊??
合并命名空间
导出成员的合并
示例
非导出成员
导出成员仅在其原有的(合并前的)命名空间内可见
合并之后,从其它命名空间合并进来的成员无法访问非导出成员
示例
命名空间与其他合并
命名空间与类合并
用于创建内部类
示例
TS不直接支持内部类
示例
用于扩展
示例
命名空间与方法合并
用于扩展?
示例
命名空间与枚举合并
扩展枚举方法
示例
非法的合并
类不能与其它类或变量合并
可参考混入功能
模块扩展
???
全局扩展
???
JSX
一种嵌入式的类似XML的语法
文件扩展名 .tsx
具体内容略过
装饰器
Decorators
Decorators
略过
混入
Mixins
Mixins
这和接口继承类的用法有什么区别?
示例
三斜线指令
Triple-Slash Directives
Triple-Slash Directives
定义
是包含单个XML标签的单行注释。 注释的内容会做为编译器指令使用。
三斜线指令仅可放在包含它的文件的最顶端。
一个三斜线指令的前面只能出现单行或多行注释,这包括其它的三斜线指令。
如果它们出现在一个语句或声明之后,那么它们会被当做普通的单行注释,并且不具有特殊的涵义。
一个三斜线指令的前面只能出现单行或多行注释,这包括其它的三斜线指令。
如果它们出现在一个语句或声明之后,那么它们会被当做普通的单行注释,并且不具有特殊的涵义。
/// <reference path="..." />
声明文件依赖
预处理输入文件
从这里开始就看不懂了
错误
使用--noResolve
如果指定了--noResolve编译选项,三斜线引用会被忽略
/// <reference types="..." />
声明包(package)依赖
???
仅当在你需要写一个d.ts文件时才使用这个指令。
/// <reference no-default-lib="true"/>
这个指令告诉编译器在编译过程中不要包含这个默认库
当传递了--skipDefaultLibCheck时,编译器只会忽略检查带有/// <reference no-default-lib="true"/>的文件。
/// <amd-module />
/// <amd-dependency />
已废弃,用module代替
JS文件类型检查
Type Checking JavaScript Files
Type Checking JavaScript Files
略过
声明文件
Declaration Files
Declaration Files
介绍
结构
举例
规范
Do's and Don'ts
Do's and Don'ts
普通类型
基础类型
不要使用Number,String,Boolean,Object(大写),
改用小写的number,string,boolean,object
改用小写的number,string,boolean,object
泛型
不要定义一个从来没使用过其类型参数的泛型类型。
原因说明
注意,直接运行例子是可以运行的,正常返回undefined。
但是如果试图获取x的name属性,那么就会报错。原因见上。
但是如果试图获取x的name属性,那么就会报错。原因见上。
回调函数类型
回调函数返回值类型
无回调的函数写void
回调函数里的可选参数
不要在回调函数里使用可选参数
???
重载与回调函数
不要因为回调函数参数个数不同而写不同的重载:
应该只使用最大参数个数写一个重载:
为什么:回调函数总是可以忽略某个参数的,因此没必要为参数少的情况写重载。 参数少的回调函数首先允许错误类型的函数被传入,因为它们匹配第一个重载。
函数重载
顺序
不要把一般的重载放在精确的重载前面
使用可选参数
不要为仅在末尾参数不同时写不同的重载:
应该尽可能使用可选参数:
使用联合类型
深入
DeepDive
DeepDive
声明文件原理:深入探究
核心概念
类型
值
命名空间
简单的组合:一个名字,多种意义
内置组合
用户组合
高级组合
利用interface添加
使用namespace添加
使用export =或import
模板
Templates
Templates
???
发布
Publishing
Publishing
???
使用
Consumption
Consumption
项目配置
Project Configuration
Project Configuration
问题
函数表达式与箭头函数表达式的区别是什么
为什么类内声明变量时不需要let?
== === 的区别是啥
== 比较值,如果类型不同,则先转化为同类型
=== 严格比较,类型不同会返回false
.d.ts是什么文件
简单讲,就是可以在 ts 中调用的 js 的声明文件,类似c++中的“*.h” 头文件,不过和 “*.h”不一样的是,它完全是个声明文件,没有任何实现代码。
在 “.d.ts” 的每一个段落中,除了最外层为 interface 外,其他的都需要 declare 关键词,而且这个词只在最外层出现。
示例
.tsx是什么文件
请查看jsx章节
Promise的用法?
示例
Dictionary的用法?
现在ES5已经可以使用Map
但是Map有坑:
使用set方法和[]都可以赋值,但是只有set才检查类型
示例
直接使用for...in...遍历不会进入循环
用for...each
用 iterator
“void 0” 与 “undefined”的区别是什么
undefined其实是个变量
void 0 则绝对返回undefined
详细解释,注意其他写法
举例
0 条评论
下一页