联合类型
用|分隔多个类型 表示取值可以为多个类型中的一种
类型别名
//用type 定义类型别名
type MyType = 1|2|3|4|5
let k:MyType = 2
枚举类型
不确定类型时尽量用unknow,不用any,unknow类型的字段不能直接赋值给已知类型的字段,必须要先确定其类型后再赋值给别人,可以用断言方式,也可以用泛型方式赋值
let e:unknown
let s:string
e='hellow'
e = 10
e = true
// s=e as string
s = <string> e
console.log(s)//true
枚举类型
关键字enum
enum Gender{male,female }//如果枚举成员没有被赋值,那么他们的值会按照从0开始的索引开始被一次复制,这里相当于male=0,female=1
let o:{name:string,gender:Gender}
o = {
name:'孙悟空',
gender:Gender.male
}
console.log(Gender.male === 0) //true
console.log(o.gender == Gender.male) //true
手动赋值
enum Gender{male=1,female=0 }
let o:{name:string,gender:Gender}
o = {
name:'孙悟空',
gender:Gender.male
}
console.log(Gender.male === 1) //true
console.log(o.gender == Gender.male) //true
## 对象类型-接口
```typescript
interface Person{
name:string;
age?:number;
[propName:string]:any;
}
定义对象类型(规格型号),可以用于对类的一部分进行抽象,还可以用于对对象的形状进行描述
interface 中的属性支持逗号、分号,不要符号三种分隔方式
可选属性
表示对象的该属性可以不存在,形式为:属性名?:类型
age?:number
任意属性
表示一个接口可以有任意属性,形式为:[propName:类型]:类型,注意定义了任意属性的值类型后,接口其他属性的值类型必须为任意类型属性子类型集
interface Person{
name:string
age:number
[propName:string]:string|number
}
只读属性
对象中某个属性只能创建的时候被赋值,可以用readonly定义
interface Person{
readonly id: number
name: string
age?:number
}
let tom:Person={
name:'Tom',
age:16
}
tom.id=12345
数组类型
有多种表示法
类型+方括号表示法
let a:number[]=[1,2,3] 数组元素只能是number类型
泛型数组:Array<elemType>
let a:Array<number> = [1,2,3]
any不限制数组元素类型
let list:any[] = [1,'a',null,{name:'aaa'}]
元组 Tuple
let x:[number,string]
x=[10,'hello']
长度固定的数组,元组存储效率会好于数组
函数类型
js中函数定义有函数声明和函数表达式两种方式
函数声明
函数的输入和输出类型约束
function sum(x:number,y:number):number {
return x + y
}
sum(1,2)
上面定义的函数如果多传入或少传入参数,ts中都会报错(可选参数和任意参数除外)
函数表达式
let sum = function(x:number,y:number):number {
return x + y
}
=>表示函数输出类型
let sum:(x:number,y:number)=>number = function(x:number,y:number):number {
return x + y
}
void 表示函数没有返回值
void和never区分就是void表示返回的时空的,有返回,但没有值,never是直接不返回了
function myfun():void{
}
可选参数
与接口中的可选属性类似,可选参数只能出现在必选参数后面
function buildName(firstName:string,lastName?:string) {
if(lastName){
return firstName + '' + lastName
}else{
return firstName
}
}
参数默认值
(paramName:paramType=默认值)
rest参数
...变量名,和ES6的rest参数一样,rest参数只能是最后一个参数
ES6的rest参数:类似arguments,但rest参数返回的是数组类型,arguments是对象类型
重载
允许一个函数接受不同数量或类型时做出不同处理
function reverse(x:number):number;
function reverse(x:string):string;
function reverse(x:number|string):number|string{
if(typeof x === 'number'){
return Number(x.toString().split('').reverse().join(''))
}else if(typeoof x === 'string'){
return x.split('').reverse().join('')
}
}
类型断言
用于手动指定一个值的类型 语法如下:
值 as 类型(推荐)
<类型>值
应用
将一个联合类型断言为其中一个类型
interface Cat {
name:string;
run():void;
}
interface Fish {
name:string;
swim():void;
}
function isFish(animal:Cat|Fish){
//想要获取联合类型的具体方法,就要将联合类型断言成指定的一种类型
if(typeof (animal as Fish).swim === 'function'){
return true
}
return false
}
类
属性和方法
类用于创建对象模型,类中有两块内容:属性和方法
属性和方法如果在前面加了static关键字则表明是静态的属性和方法,也就是类自身的属性和方法,是不可以被修改的,可以直接通过类访问,不需要通过实例去获取,没有static关键字的则表示是实例的属性和方法,可以被修改。
class Person {
name:string = '孙悟空'
age:number = 18
static name1 = '猪八戒'
sayHello(){
console.log(this.name)
}
static sayHello1(){
console.log(Person.name1)
}
}
let swk = new Person()
swk.sayHello()
swk.name = 'tom'
swk.sayHello()
Person.sayHello1()
//输出
孙悟空 18
tom 18
猪八戒
构造函数
在用new创建实例对象时实际就是调用累的constructor函数
class Person{
name:string
constructor(name:string){
this.name = name
}
sayHello(){
console.log('my name is '+this.name)
}
}
let tom = new Person('tom')
let lisa = new Person('lisa')
console.log(tom)
tom.sayHello()
lisa.sayHello()
//输出
Person { name: 'tom' }
my name is tom
my name is lisa
类的继承
子类继承父类,相当于子类拷贝了父类中的属性和方法,同时子类也可以有自己的方法和属性,如果子类中有和父类同样的方法,那么子类的方法会覆盖父类的方法,也就是重写了父类的方法。
class Animal {
name:string
age:number
constructor(name:string,age:number){
this.name = name
this.age = age
}
sayHello(){
console.log(this.name+'在叫 ')
}
}
class Dog extends Animal{
run(){
console.log('我会跑')
}
}
class Cat extends Animal{
sayHello(){
console.log('喵喵喵')
}
}
let dog = new Dog('tom',5)
let cat = new Cat('xiaoli',3)
dog.sayHello()
cat.sayHello()
dog.run()
//输出
tom在叫
喵喵喵
我会跑
属性封装
public private protected
类中用public修饰的属性或者方法表示是公有,可以在任何地方访问
类中用private修饰的属性或者方法表示是类的私有的,不能在类外部访问它,只能在类内部使用
类中用protected修饰的属性或者方法表示是受保护的,不能在类外部访问它,但可以在子类中使用
属性读写器getter setter
为了防止属性被任意篡改,比如年龄在外部被赋了个负值发生的危险,我们可以将类的属性控制前放在自身,读和写都有自己控制
(function(){
class Person{
private _name:string
private _age:number
constructor(name:string,age:number){
this._name = name
this._age = age
}
get name(){
return this._name
}
get age(){
return this._age
}
set name(value:string){
this._name = value
}
set age(value:number){
if(value > 0){
this._age = value
}
}
}
let p = new Person('lisa',19)
p.name='tom'
p.age = -10
console.log(p.name,p.age) //tom,19
})()
readonly
在类中用readonly定义的属性不可以被修改,表示只能读不能写
super
super 表示当前子类的父类,如果子类的构造函数中,必须调用父类的构造函数
class Animal {
name:string
age:number
constructor(name:string,age:number){
this.name = name
this.age = age
}
sayHello(){
console.log(this.name+'在叫 ')
}
}
class Dog extends Animal{
constructor(name:string,age:number){
super(name,age)
}
run(){
console.log('我会跑')
}
}
抽象类 abstract
用abstract定义的类,不可以被实例化,这叫抽象类,通常用来定义被子类继承的父类,抽象类里也可以定义抽象方法,定义了抽象方法后,子类就必须重写该抽象方法
abstract class Animal {
name:string
age:number
constructor(name:string,age:number){
this.name = name
this.age = age
}
abstract sayHello():void
}
class Dog extends Animal{
sayHello(): void {
}
}
let dog = new Dog('狗',4)
类实现接口 implements
定义类时可以让类去实现一个接口,也就是按照一个接口的标准去定义并实现,实现接口就是让类满足接口的条件; 接口是为了定义一个标准,来约束类,让类必须按照接口来实现,接口里定义的方法没有具体实现内容,就是为了让类去实现这个方法的。
interface MyInter{
name:string
sayHello():void
}
class MyClass implements MyInter{
name:string
constructor(name:string){
this.name = name
}
sayHello(): void {
console.log(this.name)
}
}
let c = new MyClass('zs')
c.sayHello()
泛型
在定义函数或类时,遇到不确定的类型可以用泛型表示,泛型可以指定多个,表达方式是<T,K,....>
function fn<T,K>(a:T):T{
return a
}
let res = fn(10)
let res1 = fn('10')
// 泛型类
class MyClass<T>{
name:T
}
// 泛型约束
interface LengthWise{
length:number
}
//T extends LengthWise 表明泛型T必须为LengthWise的实现类
function loggingIndentity<T extends LengthWise>(arg:T):T{
console.log(arg.length)
return arg
}
loggingIndentity({length:10})//10
loggingIndentity('111')//3
loggingIndentity(1) //1没有length属性
迭代器
let list = [4,5,6]
//for... in 关注迭代对象的键
for (let i in list){
console.log(i)//0,1,2
}
//for...of 关注迭代对象的值
for (let i of list){
console.log(i) //4,5,6
}