基础类型:
boolean,
number,
string,
数组(两种定义方式:let list: number[] = [1, 2, 3];;let list: Array<number> = [1, 2, 3];)
元组:元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同如:let x: [string, number];
枚举:enum
类型是对JavaScript标准数据类型的一个补充。 像C#等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字。
任意值:any:当不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any
类型来标记这些变量:空值void..any类型,在赋值过程中类型可以被任意改变。任意值上可以调用任意方法,访问任何属性。
变量如果在声明的时候,未指定其类型,那么它会被识别为任意值类型
类型推论:如果一开始定义的同时就赋值(let dd="1234"一开始就赋值String),那么遵循类型推论,变量为一开始赋的值的类型(即String型)。如果一开始定义时没有直接赋值(let dd;),不管之后有没有赋值,都会被推断成 any
类型而完全不被类型检查:
联合类型(Union Types)表示取值可以为多种类型中的一种:
let myFavoriteNumber: string | number;
访问联合类型时:当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法:
赋值时,根据类型推论去推论赋值
TypeScript里,undefined
和null
两者各自有自己的类型分别叫做undefined
和null
。 和 void
相似,它们的本身的类型用处不是很大:默认情况下null
和undefined
是所有类型的子类型。 就是说你可以把 null
和undefined
赋值给number
类型的变量。
never
类型表示的是那些永不存在的值的类型。never
类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型; 变量也可能是 never
类型,当它们被永不为真的类型保护所约束时。never
类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是never
的子类型或可以赋值给never
类型(除了never
本身之外)。 即使 any
也不可以赋值给never
。
类型断言::::有两种形式。
其一是“尖括号”语法:
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
另一个为as
语法:
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
变量声明:let和const::const
是对let
的一个增强,它能阻止对一个变量再次赋值。
用let替换var的原因:1,作用域规则(let声明不存在闭包问题,因为其声明的是块级作用域,不能在全局环境中调用)块作用域变量在包含它们的块或for
循环之外是不能访问的。
重载允许一个函数接受不同数量或类型的参数时,作出不同的处理
注意,TypeScript 会优先从最前面的函数定义开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前面。
2、重定义及屏蔽
我们提过使用var
声明时,它不在乎你声明多少次;你只会得到1个。let声明则限定不能在一个作用域里多次声明同一个变量
在一个嵌套作用域里引入一个新名字的行为称做屏蔽。
解构:从数组和对象中提取值,对变量进行赋值,这被称为解构.
接口:TypeScript的核心原则之一是对值所具有的shape进行类型检查,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。
1,可选属性的接口:带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个“?”符号;可选属性的好处之一是可以对可能存在的属性进行预定义,好处之二是可以捕获引用了不存在的属性时的错误。,
2,只读属性:readonly或者赋值一个对象字面量来构造一个point
readonly
vs const
最简单判断该用readonly
还是const
的方法是看要把它做为变量使用还是做为一个属性。 做为变量使用的话用const
,若做为属性则使用readonly
。(只读类型不能赋值)
跳过属性检查的方式:1,类型断言 2,将这个对象赋值给一个另一个变量。
类型断言(Type Assertion)
可以用来手动指定一个值的类型。
语法
<类型>值
或
值 as 类型
在 tsx 语法(React 的 jsx 语法的 ts 版)中必须用后一种。(应用在联合类型中不确定时报错断言)
类型断言不是类型转换,断言成一个联合类型中不存在的类型是不允许的:
详情参见:https://github.com/xcatliu/typescript-tutorial/blob/master/basics/type-assertion.md
3,函数类型
接口能够描述JavaScript中对象拥有的各种各样的外形。 除了描述带有属性的普通对象外,接口也可以描述函数类型。,
4,可索引的类型
可索引类型具有一个 索引签名,它描述了对象索引的类型,还有相应的索引返回值类型。共有支持两种索引签名:字符串和数字。 可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型.
类静态部分与实例部分的区别
当你用构造器签名去定义一个接口并试图定义一个类去实现这个接口时会得到一个错误;因为当一个类实现了一个接口时,只对其实例部分进行类型检查。
扩展接口:复制成员:interface Square extends Shape ;(Square继承Shape,可以继承多个,创造出多个接口的合成接口)let square = <Square>{};square复制了Square
接口继承类
定义的变量比接口少或多了一些属性是不允许的:(希望不要完全匹配一个形状,那么可以用可选属性(用“?”表明)或者任意属性一旦定义了任意属性,那么确定属性和可选属性都必须是它的子属性:)详情参见:https://github.com/xcatliu/typescript-tutorial/blob/master/basics/type-of-object-interfaces.md
当接口继承了一个类类型时,它会继承类的成员但不包括其实现。 就好像接口声明了所有类中存在的成员,但并没有提供具体实现一样。 接口同样会继承到类的private和protected成员。 这意味着当你创建了一个接口继承了一个拥有私有或受保护的成员的类时,这个接口类型只能被这个类或其子类所实现(implement)。
这是很有用的,当你有一个很深层次的继承,但是只想你的代码只是针对拥有特定属性的子类起作用的时候。子类除了继承自基类外与基类没有任何联系
声明文件
当使用第三方库时,我们需要引用它的声明文件。需要使用 declare
关键字来定义它的类型,帮助 TypeScript 判断我们传入的参数类型对不对:比如使用jquery时,需要:
declare var jQuery: (selector: string) => any;
jQuery('#foo');
declare
定义的类型只会用于编译时的检查,编译结果中会被删除。
上例的编译结果是:
jQuery('#foo');
我们约定声明文件以 .d.ts为后缀。
然后在使用到的文件的开头,用「三斜线指令」表示引用了声明文件:
/// <reference path="./jQuery.d.ts" />
jQuery('#foo');
内置对象
是指根据标准在全局作用域(Global)上存在的对象。这里的标准是指 ECMAScript 和其他环境(比如 DOM)的标准。
联合类型
联合类型(Union Types)可以通过管道(|)将变量设置多种类型,赋值时可以根据设置的类型来赋值 例:var val:string|number
类
关于继承,ES6与TypeScript有以下共同点
- 都是采用
extends
语法进行继承 - 在
constructor
中都需要首先使用super(xxx)
调用父类构造函数,然后才能给this进行赋值 supper
作为方法时指向父类构造函数,而作为对象且在普通方法中时指向父类的原型,在静态方法中时指向父类。(但TypeScript中直接使用静态方法中的supper
获取属性值时会报错Only public and protected methods of the base class are accessible via the 'super' keyword.
(表示supper
在子类静态方法中只能调用父类的静态方法),可是最终编译的结果却符合ES6规范,这里可能是TypeScript编译器中的BUG,有兴趣的可以自己试试)- 最终都是通过ES5的原型链进行继承
不同点
- TypeScript提供抽象类,抽象方法,和接口继承,具体使用请参考TypeScript官方文档。
- TypeScript可以对类中属性或方法使用访问限定符。
TypeScript 命名空间
命名空间一个最明确的目的就是解决重名问题。使用 namespace 来定义
namespace SomeNameSpaceName { export interface ISomeInterfaceName { } export class SomeClassName { } }
TypeScript 模块
模块是在其自身的作用域里执行,意味着定义在模块里面的变量、函数和类等在模块外部是不可见的,除非明确地使用 export 导出它们。类似地,我们必须通过 import 导入其他模块导出的变量、函数、类等。