class 类
构造函数:
需要为构造函数指定类型注解,否则会被隐式推断为 any ;构造函数不需要返回值类型
class Person {
name:string
age:number
constructor(name:string,age:number){
this.name = name
this.age = age
}
}
let p = new Person('lf',18)
console.log(p);
类继承的两种方式:
extends(继承父类)
class Animal {
eat() {
console.log("吃狗粮");
}
}
class Dog extends Animal {
name = "旺财";
sing() {
console.log("汪汪");
}
}
let dog = new Dog();
console.log(dog.eat());
console.log(dog.name);
2 implements 关键字 (实现接口)
Person 类中必须提供 Skills 接口中指定的所有方法和属性
interface Skills {
Sing():void
Play():void
}
class Person implements Skills {
Sing(){
console.log('爱你一万年');
}
Play(){
console.log('吃鸡');
}
}
类成员可见性
public:表示公有的、公开的,公有成员可以被任何地方访问,默认可见性protected:表示受保护的,仅对其声明所在类和子类中(非实例对象)可见private:表示私有的,只在当前类中可见,对实例对象以及子类也是不可见的
// public 公开的
// protected 受保护的
// private 私有的
class Animal {
protected eat() {
console.log("吃狗粮");
}
private drink(){
console.log('喝可乐');
}
play(){
this.eat() // 可以调用eat 方法
this.drink() // 可以调用drink 方法
console.log('跳一跳');
}
}
let animal = new Animal()
// 不能调用Animal类中的eat 方法
// 不能调用Animal类中的drink 方法
animal.play()
class Dog extends Animal {
name = "旺财";
sing() {
this.eat() // 可以调用Animal类中的eat 方法
//this.drink() 不能调用Animal类中的drink 方法 (私有的)
console.log("汪汪");
}
}
let dog = new Dog();
// 不能调用Animal类中的eat 方法
// 不能调用Animal类中的drink 方法
dog.name
dog.play()
dog.sing()
readonly(只读修饰符)
readonly: 表示只读,用来防止在构造函数之外对属性进行赋值
使用 readonly 关键字修饰该属性是只读的,注意只能修饰属性不能修饰方法
接口或者 {} 表示的对象类型,也可以使用 readonly
class Person1 {
name:string
readonly age:number = 18 //默认18
constructor(a:string,b:number){
this.name = a
this.age = b
}
}
let p = new Person1('lf',20)
p.name = '路飞'
//p.age = 20 //只读,不能修改
//接口写法
interface Person2 {
readonly name:string
}
let obj:Person2 = {
name:'路飞'
}
//obj.name = '娜美' //只读,不能修改
let obj1:{readonly name:string} = {
name:'路飞'
}
//obj1.name = '娜美' //只读,不能修改
类型兼容性
-
Structural Type System(结构化类型系统)TS采用的是结构化类型系统,也叫做duck typing(鸭子类型),类型检查关注的是值所具有的形状 -
Nominal Type System(标明类型系统)(比如,
C#、Java等)
interface Named {
name: string;
}
class Person {
name: string;
}
let p: Named;
p = new Person(); //ts可以兼容 C#、Java 等不能兼容
-
接口兼容性:
成员多的 可以赋值给成员少的
interface X {
a: number;
b: number
}
interface Y {
a: number;
b: number;
c: number
}
let x: X = { a: 1, b: 2 }
let y: Y = { a: 1, b: 2, c: 3 }
x = y // YES
y = x // ERROR 类型 "X" 中缺少属性 "c",但类型 "Y" 中需要该属性。
-
函数的兼容性
比较参数: 参数可以少但是不能多
let x = (a: number) => 0;
let y = (b: number, s: string) => 0;
y = x; // YES
x = y; // Error 不能将类型“(b: number, s: string) => number”分配给类型“(a: number) => number”。
比较返回值: 返回值类型必须是目标函数返回值类型的子类型。(**少了不行,多了可以**)
let x = () => ({name: 'Alice'});
let y = () => ({name: 'Alice', location: 'Seattle'});
x = y; // YES
y = x; // Error, 不能将类型“() => { name: string; }”分配给类型“() => { name: string; location: string; }”。
// 类型 "{ name: string; }" 中缺少属性 "location",但类型 "{ name: string; location: string; }" 中需要该属性。
交叉类型
- 交叉类型
&:功能类似于接口继承extends,用于组合多个类型为一个类型(常用于对象类型)
interface P1 {name:string}
interface P2 {age:number}
type P3 = P1 & P2 //P3同时拥有了P1和P2所有属性类型
let person:P3 = {
name:'路飞',
age:18
}
- 交叉类型
&和接口继承extends的对比: l 相同点:都可以实现对象类型的组合。 l 不同点:两种方式实现类型组合时,对于同名属性之间,处理类型冲突的方式不同。
泛型
泛型 : 在定义函数,接口,类的时候不能预先确定数据类型,而是在使用函数,接口,类的时候才能确定数据类型
function getArr<T>(value:T,count:number) : T[] {
const arr:Array<T> = [];
for(let i = 0;i<count;i++){
arr.push(value)
};
return arr;
}
const arr1 = getArr<string>('timi',5)
const arr2 = getArr<number>(100.2222,5)
console.log(arr1[0].split(',')); // arr1[0] 有智能提示
console.log(arr2[0].toFixed(2)); // arr2[0] 有智能提示
//多个泛型函数参数
function getArr<K, V>(value1: K, value2: V): [K, V] {
return [value1, value2];
}
const arr1 = getArr<string,number>("tim", 22.222)
console.log(arr1[0].split(''));
console.log(arr1[1].toFixed(1));