官方:
TypeScript的核心原则之一是对值所具有的结构进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在TypeScript里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。
简单来说, 接口中可以定义属性和方法, 声明属性的类型以及方法(参数,返回值等)的类型
当一个有参的函数(使用接口)被调用时,类型检查器会检查函数是否存在参数并检查参数类型是否对应,不会检查属性的顺序, 只要相应的属性存在并且类型是对的即可
定义接口时, 使用interface关键字来修饰
可选属性 ? 修饰
readonly 修饰只读属性
interface objType { name: string, age: number,color ?: string, // ? 可选属性readonly sex ?: string, // 只读属性readonly, 属性只有再被创建的时候才可被修改
}function fun1(obj: objType) {console.log(`${obj.name}----${obj.age}`);
}interface SquareConfig {color?: string;width?: number;
}
function createSquare(config: SquareConfig): { color: string; area: number } { }
let mySquare = createSquare({ colour: "red", width: 100 });
//注意传入createSquare的参数拼写为colour而不是color。 在JavaScript里,这会默默地失败。
//你可能会争辩这个程序已经正确地类型化了,因为width属性是兼容的,不存在color属性,而且额外的colour属性是无意义的。
//然而,TypeScript会认为这段代码可能存在bug。 对象字面量会被特殊对待而且会经过 额外属性检查,当将它们赋值给变量或作为参数传递的时候。 如果一个对象字面量存在任何“目标类型”不包含的属性时,你会得到一个错误// error: 'colour' not expected in type 'SquareConfig'
let mySquare = createSquare({ colour: "red", width: 100 });// 绕过检查
// 1. 类型断言
const result = show({name: '小白',age: 10,price:1999,color: 'black',gender: 'Weizhi '
} as ObjType)
console.log(result);// 额外属性检查
// 对象字面量会进行额外属性检查, 非对象字面量(如: 变量)不会进行
let num:string = 'hello'
interface ObjType{name: string,age: number,price: number,color ?: string, // 可选属性// 索引签名, 代表任意个属性 使用时可继续传递 属性名是string类型, 属性值可以是 any任意类型[prop:string]: any
}
let dogObj: ObjType = {name: '旺财',age: 3,price: 188,
}
// 输出狗的信息
function show(dog:ObjType): string{return `name=${dog.name} - age= ${dog.age} - price= ${dog.price}`
}
const res = show(dogObj)
console.log(res);
show(dogObj) // 不会检查// 接口
interface PointInter {currentTime: Date;setTime(d: Date);
}
// 类实现接口 可实现多个接口, 接口名中间,分隔
class ClsImInter implements PointInter{currentTime: Date;setTime(d: Date) {this.currentTime = d;}constructor(h: number, m: number) { } // 构造器属于静态成员
}class Control {private state: any;
}
// 接口继承类
interface SelectableControl extends Control {select(): void;
}
// 类继承类,实现接口
class Button extends Control implements SelectableControl {select() { }
}
class TextBox extends Control {select() { }
}class类中包含属性,fangf,构造函数...
类的静态属性和实例属性:
实例属性: 类的实例成员, 仅当类被实例化的时候才会被初始化的属性, 访问时使用 实例名.属性名或方法名[this.属性名]
静态属性: static 修饰静态成员 所有的实例用到的属性, 归类所有,不属于具体的实例, 访问时 类名.属性名或方法名, 可赋值可修改
构造函数是静态成员, 归类所有, 不是实例上的,用于创建实例
public, private, protected, readonly(只读)
public 公共的, 可在任意位置访问其修饰的属性及方法
private 私有的, 只能在本类中访问, 其他类(包括子类中也不可访问), 若想在基类中使用,需写公共的方法,基类通过访问公共方法使用父类中的私有属性
protected 受保护的, 可在子类中访问, 通过实例不可访问
注意:
constructor构造函数可以被protected修饰, 但不能使用 provate 修饰
子类继承时, 可以将修饰范围变大, 但不能变小, e.g父类使用public修饰, 子类继承后不能使用private修饰
// 类 class 抽象概念 作用:创建实例// 声明类 使用关键字class, 类名 大驼峰式命名规则class Personn{// 特征 ---- 属性(名词)name: stringage: numbergender: number // 0 男 1女// 构造函数 new 创建对象时调用构造函数constructor(name: string, age: number, gender: number){this.name = name // 当前对象的name = 传递进来的namethis.age = agethis.gender = gender}// 行为 ---方法(动词)run(){console.log('running');}study(){console.log('study!!!');}} // 创建实例 new一个实例对象
// const kk = new Person()// 查看属性 实例名.属性
// console.log(kk.age); // undefinded
// 使用构造函数后需要传参
const kk = new Personn('haha',20,0)
console.log(kk); //Personn {name: 'haha', age: 20, gender: 0}kk.name = '空空i'
kk.age = 21
kk.gender = 1
console.log(kk); // Personn {name: '空空i', age: '21', gender: 1}使用继承来扩展现有的类
子类可使用父类公共的属性和方法, 也可包含自己独有的属性和方法, 也可重写父类中的方法
调用super()执行基类的构造函数, 子类的构造函数内部,第一行必须写super(父类构造函数中的属性)后方可使用父类中的属性
TypeScript支持通过getters/setters来截取对对象成员的访问。有效的控制对对象成员的访问
子类可通过存取器来获取和修改基类中的属性值
子类可以写与基类中同名方法, 对基类的方法进行修改, 当调用时, 如果子类重写了则先调子类中的
// 继承
class Animall{// 公有属性name: stringpublic weight: number// 私有属性private master: string// 受保护的属性protected type: string// 只读属性 必须在声明时或构造函数中赋值readonly fullName : string = 'ahahaha'// 构造函数 也可使用 private 等修饰constructor(name: string, weight: number){this.name = namethis.weight = weight}eat(){console.log('Animall---都会eatting!!!');}// getter 访问该方法获取私有属性 基类对象需要 通过公共方法 gettergetMaster(): string{return this.master}// setter 修改私有属性 基类对象需要 通过公共方法 好处: 控制权限, 修改条件等setMaster(val: string){if(!val || val.replace(/(^\s*|\s*$)/g,'') === ''){this.master = val}}
}class Dogg extends Animall{// name: string// weight: numbercolor: string // 可以在构造函数中使用 public 修饰, 相当于在类中声明了一个属性// 构造函数constructor(name: string, weight: number, color: string){// 使用super 子类包含了一个构造函数, 必须调用super() 他会执行基类的构造函数super(name,weight)this.color = color}// 狗特有的方法gatekeeper(){console.log('看门Dog!!!!!');}// 重写(override) 子类重写父类的方法,名字可相同, 子类实例调用时,调用的是子类的方法, 而不是父类eat(){console.log('Dog eatting --!!!==> 重写eat');}
}class Catt extends Animall{// name: string// weight: numberspecies: string// 构造函数constructor(name: string, weight: number, species: string){// 使用super 子类包含了一个构造函数, 必须调用super() 他会执行基类的构造函数super(name,weight)this.species = species}catchMouse(){console.log('Cat抓老鼠!!!');}
}const dogg = new Dogg('ww',12,'blue')
// 调用自己独有的方法
dogg.gatekeeper()
const catt = new Catt('qqq',3,'wwww')
catt.catchMouse()
const animall = new Animall('ee',2)
animall.eat()兼顾类和接口的作用, 不能创建实例, 但可以被类继承
抽象类和接口中均定义方法名, 但未实现,不包含方法体
子类如果继承了抽象类, 那么子类中必须实现抽象类中没有实现的抽象方法
// 抽象类 abstract
// 兼顾类和接口的作用, 不能创建实例, 但可以被类继承
// 抽象类和接口中均定义方法名, 但未实现,不包含方法体
// 子类如果继承了抽象类, 那么子类中必须实现抽象类中没有实现的抽象方法
abstract class Animal1 {// 构造函数 也可使用 private 等修饰constructor(public name: string) {}// 抽象方法, 没有实现的方法, 子类必须实现abstract sing(): void// 普通方法dance(): void {console.log(this.name)}public get Name(): string {return this.name}public set Name(v: string) {this.name = v}
}class Dog1 extends Animal1 {constructor(public name: string) {super(name)}// 抽象基类的抽象方法必须在子类中实现sing(): void {console.log('dogsing')}
}class Cat1 extends Animal1 {constructor(public name: string) {super(name)}sing(): void {console.log('catsing')}
}const dogs1 = new Dog1('111')
dogs1.sing()
// dogs2 类型 为 Dog1 类型
let dogs2: Dog1// 抽象类 不能创建实例
// const qq = new Animal1()
// console.log(qq);// 类也是一种类型,类可以被当做接口使用
// 接口可以继承类, 接口可以继承接口
class Pointt {x: number;y: number;
}
interface Point3d extends Pointt {z: number;
}
let point3d: Point3d = {x: 1, y: 2, z: 3};官方介绍:
函数是JavaScript应用程序的基础。 它帮助你实现抽象层,模拟类,信息隐藏和模块。 在TypeScript里,虽然已经支持类,命名空间和模块,但函数仍然是主要的定义 行为 的地方。 TypeScript为JavaScript函数添加了额外的功能,让我们可以更容易地使用。
简单来讲, 函数中主要定义行为, 是为执行特定任务的代码块。ta是特殊的对象,可以被调用,在调用时被执行。
TS函数可以创建具名函数(有名字的函数)和匿名函数
//有名函数
function show(){ //要执行的操作
}
//匿名函数
let fun = function(){//要执行的操作
}
//立即执行函数
let fn = (function(){})()
let fn = (function(){}())
//函数表达式
const add() => { }为函数定义类型
// 参数x,y类型为number, 函数返回值类型为number, 若在赋值语句的一边指定了类型但是另一边没有类型的话,TypeScript编译器会进行类型推断,自动识别出型
let myAdd = function(x: number, y: number): number { return x + y;
};
// 箭头函数 Void没有任何类型, 一般情况下用于函数的返回类型, 当函数没有返回值时,类型就为void
let fun2 = (msg: string, age: number) : void =>{// 函数也有类型, 没有返回值时,类型就为void
}
// 匿名函数, 名字为 myAdd 向函数中传递两个参数,baseValue,increment,类型均为number, 函数返回值为number 匿名函数中 x <==> baseValue, y <==> increment
let myAdd: (baseValue: number, increment: number) => number = function(x: number, y: number): number { return x + y;
};可选参数和默认参数
当函数需要传参时, 要传递的参数个数必须与函数期望参数个数保持一致
参数可设置默认值
参数可传可不传 ? 实现可选
传递多个参数
// 无参函数
function show(){ }
// 有参函数
function show1(name:string){ }
// 可选参数 必须位于已知参数之后
function show2(age:number, name?:string) : void { }
// 参数默认值
function buildName(firstName: string, lastName = "Smith") { }
// 给参数默认值, 并且传递的参数 ? 可有可无 参数对象默认值为{}, 当函数调用未传参时,使用默认值
function show({uname = 'mm', age = 21, tel = '158'} : { uname?:string,age?:number,tel?:string} = {}){return `${uname}-${age}-${tel}`
}
//把所有参数收集到一个变量里
function buildName(firstName: string, ...restOfName: string[]) {return firstName + " " + restOfName.join(" ");
}
let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");顶级的非方法式调用会将 this视为window。 (注意:在严格模式下,this为undefined而不是window
参考文档: https://www.tslang.cn/docs/handbook/functions.html
下一篇:C#基础到入门(一篇就够了)