原始类型
:Number,String,Boolean,null,undefined,Symbol 引用类型
:Array,Function,Object TypeScript在ES6的数据类型基础上,新增了如下数据类型:void, any, never, 元组,枚举,高级类型
web
let cml: number = 1
// es5: let cml = 1
复制代码
let cml: string = '1'
// es5: let cml = '1'
复制代码
let cml: boolean = true
// es5: let cml = true
复制代码
let cml:null = null
// es5: let cml = null
复制代码
let cml:undefined = undefined
// es5: let cml = undefined
复制代码
const s2: symbol = Symbol(); // TypeScript
const s1 = Symbol(); // es5
console.log(s1 === s2) // false
复制代码
void类型能够被赋值为undefined和null,可是不能被赋值其余的,好比stringtypescript
let cml:void = undefined
// es5: let cml = undefined
cml = null
复制代码
小结:
TypeScript会作静态类型检查,当一个变量被定义了某种类型后,再赋值为其余类型的值时,则会有报错提示 数组
可是
markdown
2. 被定义为null和undefined类型的,只能赋值为它自己函数
// let cml: Object = {x: 1, y: 1} // 不能直接写Object,须要具体定义包含的属性以及对应的类型
let cml: {x: number, y: number} = {x: 1, y: 1}
cml.x = 2
console.log(cml)
复制代码
1 类型+方括号
ui
let cml: number[] = [1, 2, 3]
// es5: let web = [1, 2, 3]
let web: any[] = [1, '2', true]
复制代码
2 泛型
this
let cml: Array<number> = [1, 2, 3]
// es5: let cml = [1, 2, 3]
复制代码
3 接口es5
类数组: 内置对象:IArgumenTypeScript, NodeList, HTMLCollectionspa
function web(name: string, age: number) {
let args: IArgumenTypeScript = argumenTypeScript;
console.log(args); // { '0': 'web', '1': 1 }
}
web('web', 1)
复制代码
元组是一种特殊的数组,限定了数组的类型和个数翻译
let cml: [string, number] = ['666', 666]
console.log(cml) // [ '666', 666 ]
复制代码
使用下标
的方式,能够只对其中一项赋值,可是对整个对象
赋值时,必须是完整的,且类型不能错,个数不能多也不能少
let cml: [string, number] = ['666', 666]
cml[0] = '888'
console.log(cml) // ['888', 666]
cml[1] = 888
console.log(cml) // ['888', 888]
cml = ['888', 888]
console.log(cml) // ['888', 888]
cml = ['888', 888, '888'] // 报错
复制代码
元组的越界:能够经过push的方式放入更多的元素,能够push,可是仍然不能访问
let cml: [string, number] = ['666', 666]
cml.push('888')
console.log(cml) // ['666', 666, '888']
console.log(cml[2]) // 报错
复制代码
any类型能够任意赋值,不写至关于any
let cml:any = '123'
cml = 123
复制代码
never 类型表示的是那些永不存在的值的类型。例如,never 类型是那些老是会抛出异常或根本就不会有返回值的函数表达式。
// 抛出异常的函数
let error: never = () => {
throw new Error('error')
}
// 死循环函数
let endLess: never = () => {
while(true) {}
}
复制代码
let cml:string | number
cml = '123'
cml = 123
复制代码
类型断言
是针对联合类型,能够经过断言为变量指定一个类型
function cml(a: number | string): void {
console.log(a.length) // 报错
console.log((<string>a).length) // OK
}
复制代码
类型别名
除了规定的string/number等类型,TypeScript还支持自定义类型
type Cml = '666' | '888'
function cmlFun(a: Cml): void {
console.log(a)
}
cmlFun('666') // OK
cmlFun(666) // 报错
复制代码
enum Gender {Male, Female}
console.log(Gender) // {'0': 'Male', '1': 'Female', 'Male': 0, 'Female', 1}
console.log(Gender['0']) // Male
console.log(Gender['1']) // FeMale
console.log(Gender['Male']) // 0
console.log(Gender['Female']) // 1
复制代码
对应的ES5的写法
// typescript
enum Gender {Male, Female}
// ES5
var Gender;
(function (Gender) {
Gender[Gender["Male"] = 0] = "Male";
Gender[Gender["Female"] = 1] = "Female";
})(Gender || (Gender = {}));
复制代码
enum Direction {
NORTH, // 默认0
SOUTH, // 默认1
EAST, // 默认2
WEST, // 默认3
}
let dir: Direction = Direction.EAST;
console.log('dir', dir) // 2
复制代码
默认为0,1,2,3...,若是自定义数字,则后面的枚举在前一个枚举值上加1
enum Direction1 {
NORTH = -1,
SOUTH, // 变成0
EAST = 4,
WEST, // 变成5
}
复制代码
注意,自加的枚举数值,不保证和已经设定的数值不重合
enum Direction1 {
NORTH = 1,
SOUTH = 0,
EAST,
WEST,
}
console.log(Direction1)
复制代码
也能够把数字变成小数
enum Direction1 {
NORTH = 1.5,
SOUTH, // 2.5
EAST, // 3.5
WEST, // 4.5
}
console.log(Direction1)
复制代码
enum Direction1 {
NORTH = 'a',
SOUTH = 'b',
EAST = 'c',
WEST = 'd',
}
console.log(Direction1) // { NORTH: 'a', SOUTH: 'b', EAST: 'c', WEST: 'd' }
console.log(Direction1['NORTH']) // a
console.log(Direction1['a']) // undefined
复制代码
常量枚举是它是使用const
关键字修饰的枚举,普通枚举有对象,常量枚举没有对象,对象实体只存在于TypeScript中,当翻译为ES5代码时,被删除了。
用途:当咱们不须要这个对象,只须要对象里的值时,适用常量枚举,能够减小编译时的代码
// TypeScript 代码
const enum Gender {Male, Female}
let cml: Gender = Gender['Female']
console.log(cml) // 1
// ES5 代码
var cml = 1 /* 'Female' */;
console.log(cml);
复制代码
异构枚举的成员值是数字和字符串的混合:
enum Cml {
A,
B,
C = "c",
D = "d",
E = 8,
F,
}
复制代码
数字枚举和字符串枚举不一样的是,数字枚举相对字符串枚举多了 “反向映射”:
console.log(Cml[0]) // A
console.log(Cml['A']) // 0
console.log(Cml['C']) // c
console.log(Cml['c']) // undefined
复制代码
// 定义一个接口
interface IPerson {
name: string,
age: number
}
// 实例化
let p1: IPerson = {
name: 'web',
age: 18
}
复制代码
一个变量,如上面的p1,若是被声明为某一种接口的实例,则变量拥有的属性必需要和接口定义的同样,不能多也不能少,不然会报错。
interface IPerson {
name: string,
age?: number
}
// 实例化
let p1: IPerson = {
name: 'web',
}
复制代码
interface IPerson {
name: string,
[propName: string]: boolean | string
}
let p1: IPerson = {
name: '123',
married: false, // ok
country: '123' // ok
age: 123 // 报错
}
复制代码
若是设定了任意属性,那么全部的肯定属性或者可选属性必须是任意属性的子集。
interface IPerson {
readonly name: string,
age: number
}
let p1: IPerson = {
name: '123',
age: 18
}
let p2: IPerson = {
name: '456', // ok
age: 18
}
p1.name = '456' // 报错
p1.age = 18
复制代码
readonly,指的是若是不在每次对象赋值状况下,是不能修改值的。
TypeScript有四种方式去定义函数:
函数的声明
// ES5里函数的声明
function cml(x, y) {
return x + y
}
console.log(cml(1, 2)) // 3
// TypeScript里函数的声明
function cml(x: number, y: number): number {
return x + y
}
console.log(cml(1, 2)) // 3
复制代码
函数的表达式
// ES5函数的表达式
let cml = function(x, y) {
return x + y
}
console.log(cml(1, 2)) // 3
// TypeScript里函数的表达式
let cml = function(x: number, y: number): number {
return x + y
}
console.log(cml(1, 2)) // 3
复制代码
函数的别名
type cmlFun = (x: number, y: number) => x + y
let cml: Cml = (a, b) => a + b
console.log(cml(1, 2)) // 3
复制代码
接口形式定义函数
interface ICml {
(x: number, y: number): number
}
let cml: ICml = function(x: number, y: number) : number {
return x + y
}
console.log(cml(1, 2)) // 3
复制代码
一个可选参数后面不能再有肯定(必须)参数
function cml(x: number, y?: number): number {
y = y || 0
return x + y
}
console.log(cml(1, 2)) // 3
console.log(cml(1)) // 1
复制代码
回忆一下ES5里的argumenTypeScript和ES6里的args ES5的argumentTypeScript
function cml() {
let sum = 0
for(let item of arguments) {
sum = sum + item
}
return sum
}
console.log(cml(1, 2, 3)) // 6
复制代码
ES6的args
function cml(...args) {
let sum = 0
for(let item of args) {
sum = sum + item
}
return sum
}
console.log(cml(1, 2, 3)) // 6
复制代码
TypeScript里的剩余参数
function cml(...args: number[]) {
let sum: number = 0
for(let i: number = 0; i < args.length; i ++) {
sum = sum + args[i]
}
return sum
}
console.log(cml(1, 2, 3)) // 6
console.log(cml(1, '2', 3)) // 报错
复制代码
C++
里的函数重载:函数能够重名,可是参数个数需不一样,或者参数个数相同可是参数类型不一样,编译器经过参数的个数和类型来判断究竟是调用了哪一个参数。
TypeScript
的函数重载,仍是只有一个函数,可是能够对不一样的参数组合进行静态类型检查
function cmlFun(arr: number[]) function cmlFun(arr: string[]) function cmlFun(arr: any[]) { if (typeof(arr[0]) === 'number') { return arr.reduce((pre, cur) => pre + cur) } else if (typeof(arr[0]) === 'string') {
return arr.reduce((pre, cur) => pre + cur)
}
}
console.log(cmlFun([1, 2, 3])) // 6
console.log(cmlFun(['1', '2', '3'])) // 123
复制代码
ES6里的类和继承
// 父类
class Father {
constructor (name, age) {
this.name = name
this.age = age
}
}
// 子类
class Son extends Father{
constructor(phone, ...args) {
super(...args)
this.phone = phone
}
f() {
console.log('this.name', this.name)
}
}
let s = new Son('17807727381', '父类', '36')
s.f() // this.name 父类
复制代码
static静态属性和静态方法不能经过new的方式调用。
class Father {
static phone = '17723812637'
static f() {
console.log('this.phone', this.phone)
}
constructor (name, age) {
this.name = name
this.age = age
}
}
let fa = new Father('17807727381', '父类', '38')
fa.f() // 报错
Father.f() // this.phone 17723812637
复制代码
用于修饰类的属性以及方法,用public修饰的属性和方法在类内、外均可以调用。
class Father {
// 须要先定义
public name: string
public age: number
public constructor (name, age) {
this.name = name
this.age = age
}
public f() {
console.log(this.name, this.age)
}
}
let fa = new Father('父类', 36) // 有构造函数,参数不能省略
fa.f() // 父类 36
复制代码
用于修饰类的属性以及方法,用protected修饰的属性和方法,只能由类或者子类的函数访问。
// 父类
class Father {
protected name: string
public age: number
public constructor (name, age) {
this.name = name
this.age = age
}
f1() {
console.log('this.name', this.name)
}
}
// 子类
class Son extends Father{
public phone: string
constructor(phone, ...args: [string, number]) {
super(...args)
this.phone = phone
}
f2() {
console.log('this.name', this.name)
}
}
let fa = new Father('父类', 36)
fa.f1() // this.name 父类 (父类经过函数访问: OK)
let s = new Son('17807727381', '父类', 36)
s.f2() // this.name 父类 (子类经过函数访问: OK)
let fa = new Father('父类', 36)
console.log(fa.name) // 报错
console.log(fa.age) // 36
复制代码
用于修饰类的属性以及方法,用protected修饰的属性和方法,只能由类函数访问
// 父类
class Father {
private name: string
public age: number
public constructor (name, age) {
this.name = name
this.age = age
}
f1() {
console.log('this.name', this.name)
}
}
// 子类
class Son extends Father{
public phone: string
constructor(phone, ...args: [string, number]) {
super(...args)
this.phone = phone
}
f2() {
console.log('this.name', this.name) // 报错
}
}
let fa = new Father('父类', 36)
fa.f1() // this.name 父类 (父类经过函数访问: OK)
let s = new Son('17807727381', '父类', 36)
s.f2() // 报错 (子类经过函数访问: 不OK)
let fa = new Father('父类', 36)
console.log(fa.name) // 报错
console.log(fa.age) // 36
复制代码
抽象类:不可实例化,不能直接new出实例来
abstract class Father {
// 须要先定义
public name: string
public age: number
public constructor (name, age) {
this.name = name
this.age = age
}
public f() {
console.log(this.name, this.age)
}
}
let fa = new Father('父类', 36) // 报错
fa.f()
复制代码
抽象方法的使用, 若是子类继承的父类里有抽象方法,则需在子类里实现父类的抽象抽象方法
abstract class Father {
// 须要先定义
public name: string
public age: number
public constructor (name, age) {
this.name = name
this.age = age
}
public abstract f1(): void
}
class Son extends Father{
public phone: string
constructor(phone, ...args: [string, number]) {
super(...args)
this.phone = phone
}
public f2(): void {
console.log('this.name', this.name)
}
public f1(): void {
console.log('this.name', this.name)
}
}
let fa: Father = new Son('17836762323', '父类', 36)
fa.f1() // this.name 父类
复制代码