背景
下面是TS的一些基础知识,确实有点宽泛,加深自己的理解,之后,还会针对不同的知识点来写文章
基础类型
数组
const arr1: string[] = ['123'];
const arr2: Array<string> = ['qwe'];
类型断言
通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用。
有两种方式,一种是尖括号的形式,<类型> xxx, 另一种是as的形式 (xxx as string)
function getLength (n: string | number) {
if ((<string>x).length) {
return (x as string).length;
} else {
return x.toString.length;
}
}
类型推断
接口 interface
函数类型
接口除了可以描述普通的对象之外,也可以描述函数类型
interface SearchFun {
(source: string, str: string): boolean
}
// 定义一个函数,该类型就是上面定义的接口
let search: SearchFun = function (source: string, str: string): boolean {
return source.search(str) > -1;
}
类类型
总结: 接口和接口之间叫继承, 类和接口之间叫实现
interface Fly {
flys(): void
}
class TheFly implements Fly {
flys() {
console.log('1');
}
adb () {
}
}
// 2
interface Flys {
sendFly():void
}
class Person implements Fly, Flys {
sendFly () {
}
flys() {
console.log('1');
}
}
// 定义一个接口,可以继承多个接口
interface MoreFly extends Fly, Flys {
}
//
类
类和类之间如果要有继承关系,需要使用extends关键字
子类中可以调用父类中的构造函数,使用的是super关键字
子类中可以重写父类中的方法
// TS 中类的定义和使用
class Person {
name: string
age: number
constructor (age: number = 12) {
this.age = age;
this.name = '1';
}
sayHi (name: string) {
console.log('1')
}
}
class Students extends Person {
constructor (age: number) {
// 调用父类中的构造函数
super(age)
}
// 可以调用父类中的方法
sayHi () {
super.sayHi('qwe');
}
}
多态
父类型的引用指向了子类型的对象
不同类型的对象针对相同的方法,产生了不同的行为
类中成员的修饰符 public private protected readonly
public 默认的访问修饰符,代表公共的,任何位置都可以访问类中的成员
private修饰符 私有属性,只能在类中使用,不能在类外面使用,特别是子类中也是无法使用的
protected 修饰符,外部是不能使用的,子类中可以使用
readonly 修饰符,对类中的属性进行修饰,但是,不能在外部修改了;但是,构造函数中,可以对只读的属性进行修改
一旦使用readonly进行修饰之后,就有了一个age属性成员
下面的例子,修饰器还可以用在构造函数的参数上
class Person {
name: string
constructor (readonly age: number = 12) {
this.age = age;
this.name = '1';
}
sayHi (name: string) {
console.log('1')
}
}
存取器 get set
截取对象成员的访问
class Person {
firstName: string = 'liu'
lastName: string = 'yongsheng'
get fullName () {
return this.firstName + '_' + this.lastName;
}
set fullName (val) {
let name = val.split('_');
this.firstName = name[0];
this.lastName = name[1];
}
}
let p = new Person();
// 注意fullName 不是函数
console.log(p.fullName);
p.fullName = 'abc_qwe';
静态成员 static
在类中通过static修饰的属性或者方法
静态成员是通过类名+'.' 的形式来访问的(Person.abc)
这些属性存在于类本身上面而不是实例对象上面
/*
静态属性,是类对象的属性
非静态属性,是类的实例对象的属性
static不能出现在构造函数的前面
*/
class Person {
static name:string = 'lys'
}
console.log(Person.name);
抽象类 abstract
抽象类作为其他派生类的基类使用。
抽象类不能被实例化
抽象类里面的抽象方法,不能有具体的实现
abstract class Animal {
abstract eat():void
// 报错,不能有具体的实现
// abstract eat():void {
// console.log('eat');
// }
}
class Dog extends Animal {
// 重新实现抽象类中的方法
eat () {
console.log('111');
}
}
// let bird = new Animal(); 报错,抽象类是不能被实例化的
TS中的函数
可选参数和默认参数
const fun = function (a: string = 'dongfang', b?: number): string {
}
剩余参数 ...rest
rest参数,一定要放在函数声明的时候的所有参数之后
function Fun (a: string, ...args: string[]) {
}
Fun('q', 'qw', 'e', 'r');
函数重载
函数的名字相同,但是函数的参数及个数是不同的
// 函数重载的声明
function add(x: string, y: string): string
function add(x: number, y: number): number
function add(x: string | number, y: string | number): string | number | undefined {
// 在实现上我们要注意严格判断两个参数的类型是否相等,而不能简单的写一个 x + y
if (typeof x === 'string' && typeof y === 'string') {
return x + y
} else if (typeof x === 'number' && typeof y === 'number') {
return x + y
}
}
泛型
在定义函数,接口,或者类的时候,不能确定要使用的类型,而是在使用的时候,确定要使用的类型
// 多个泛型参数的函数
function getMsg<K,V> (val1: K, val2: V): K[] {
return [val1];
}