一、常用方法
//1、类型推断(会根据你给变量存放的初始值来进行变量类型限定)
let str = '123';
str = 10;//会报警告
//2、类型注解
let str: string = '123';
//3、类型断言
let numArr = [1, 2, 3];
const result = numArr.find(item => item > 2) as number;
result * 5;
二、基础类型和联合类型
// 基础类型
let v1: string = 'abc'
let v2: number = 1
let v3: boolean = true
let nu: null = null
let un: undefined = undefined
// 联合类型(用来类型限定/具体值的限定)
let v4: string | null = null//类型限定:默认null可以分配给任意其他类型,但是如果开启了配置项中的strictNullChecks,就不能随便将null分配给其他类型,这时候就可以用这个方式进行标记
let v5: 1 | 2 | 3 = 2 //具体值的限定
三、数组+元组+枚举+void+接口+type+泛型
//数组
let arr: number[] = [1, 2, 3]
let arr1: Array<string> = ['a', 'b', 'c']
// 元组:可以存储多个数据,但是限定了存储的数据个数以及每个数据的类型
//string?后面的?说明是这个元素可有可无,也就是说这个t1长度可以是2也可以是3,所以t1和t2都没问题
let t1: [number, string, string?] = [1, 'a']
let t2: [number, string, string?] = [2, 'b', 'c']
t1[0] = 2//类型正确,无报错
t1[0] = 'q'//类型不对,会报错
// 枚举:会自动做值的分配,默认从0分配,也就是A的值是0,B的值是1,C的值是2
enum myEnum { A, B, C }
console.log(myEnum.A)//输出0
console.log(myEnum[0])//输出A
// void空:viod只能被分配undefined值(严格模式),一般不用于给变量赋值,通常在函数没有返回值(默认是undefined)的时候用
// a = 10是给了a一个默认值,c?: boolean中间的?说明这个是可有可无的
function myFn(a = 10, b: string, c?: boolean, ...rest: number[]): void {
console.log(a + b)
}
const f = myFn(20, 'abc', true, 1, 2, 3)
// 接口
interface Obj {
name: string,
age: number,
}
const obj: Obj = {
name: 'a',
age: 10
}
// type:类型别名
type MyUserName = string | number
let a: string | number = 10
let b: MyUserName = 'abc'
// 泛型
function myFn1(a: number, b: number): number[] {
return [a, b]
}
function myFn2<T>(a: T, b: T): T[] {
return [a, b]
}
myFn2<number>(1, 2)
myFn2<string>('a', 'b')
四、函数重载
函数重载是指:创建多个名称一样,参数类型和返回值不同的函数,以达到能够编写一个函数,实现多种功能的目的
function hello(name: string): string
function hello(age: number): string
function hello(value: string | number): string {
if (typeof value === 'string') {
return '你好,我的名字是' + value
} else if (typeof value === 'number') {
return '你好,我的年龄是' + value
} else {
return '非法格式'
}
}
hello('abc')
hello(18)
五、接口继承
// 接口继承(除了可以进行一些类型的设置,还可以进行继承的操作)
interface Parent {
props1: string,
props2: number
}
interface Child extends Parent {
props3: string
}
const obj: Child = {
props1: 'a',
props2: 1,
props3: 'b'
}
六、类的修饰符
- 类的修饰符有可选属性、属性默认值、私有属性、受保护属性、静态成员
- 可以通过 tsc --init 命令,创建一个初始化的配置文件
- 可选属性需要通过?设置,aaa那样是不对的,要像bbb那样设置
- 用=设置默认值
- 属性有公有、私有、受保护3类
- public:公有的,可以在任何地方被访问到,默认所有的属性和方法都是public的
- protected:受保护的,只能在类的内部以及派生类(子类)中访问,但不能在类的外部访问。
- private:私有的,只能在类的内部访问,即使是自己的实例、继承的子类都无法访问被private修饰的内容。
- static:的静态成员,静态成员属于类本身,而不属于类的实例,可以在不创建类的实例的情况下直接访问。
静态属性:1. 使用static关键字来定义静态属性。2. 静态属性可以在类的内部和外部通过类名来访问,并且在子类中可以被覆盖。3. 静态属性不能被继承。静态属性只属于类本身,而不属于类的实例;
静态方法:1. 使用static关键字来定义静态方法。2. 静态方法可以在类的内部和外部通过类名来调用,并且在子类中可以被覆盖。3. 静态方法只能访问静态属性和调用其他静态方法,不能访问实例属性和调用实例方法。4. 静态方法不能被继承。静态方法只属于类本身,而不属于类的实例
修饰符 | 类A内 | 子类B内 | 实例a | 子类的实例b | 类A | 子类B |
---|---|---|---|---|---|---|
public | this.title | this.title | a.title | b.title | A.title报错 | B.title报错 |
protected | this.innerData | this.innerData | a.innerData报错 | b.innerData报错 | A.innerData报错 | B.innerData报错 |
private | this.tempData | this.tempData报错 | a.tempData报错 | b.tempData报错 | A.tempData报错 | B.title报错 |
static | this.author报错A.author正确 | this.author报错A.author正确B.author正确 | a.author报错 | b.author报错 | A.author | B.author |
class A {
//public aaa: string(aaa是可选属性,没有进行初始化,但是这种写法在严格模式的时候是会报错的,正确的写法是像下面的bbb那样)
public bbb?: string
public ccc = 100 //用=设置默认值,未设置数据类型,ts会类型推断
public title: string
protected innerData?: string //受保护属性:只能在类A和子类B中访问
private tempData?: string //私有属性:只能在类A中访问
static author:string //静态属性:将属性设置给类本身,而不是类的实例
private static time: string //私有的静态属性
readonly num: number = 10 //只读属性,无法修改
constructor(title: string) {
this.title = title //公有属性
//A.title(报错)
this.innerData //受保护属性
//A.innerData(报错)
this.tempData //私有属性
//A.tempData(报错)
//this.author(报错)
A.author //静态属性
//this.time(报错)
A.time //time是私有的静态属性,只能在这里用,this.time都会报错
}
}
class B extends A {
constructor(title: string) {
super(title)
this.title //公有属性
//B.title(报错)
this.innerData //受保护属性
//B.innerData(报错)
// this.tempData //(报错,私有属性)
// B.tempData(报错)
// this.author(报错)
B.author //静态属性
}
}
const a = new A('标题A');
const b = new B('标题B');
console.log(a.title, b.title);
//console.log(A.title, B.title);(均报错)
// console.log(a.innerData, b.innerData);(均报错)
// console.log(A.innerData, B.innerData);(均报错)
// console.log(a.tempData, b.tempData);(均报错)
// console.log(A.tempData, B.tempData);(均报错)
// console.log(a.author, b.author);(均报错)
console.log(A.author, B.author);
// a.num = 8(报错)
七、存取器
类似于js里的getter和setter,某些属性不愿意被外部的人随便读取,这时候就可以用get和set存取器
一般私有属性前面加_,存取器同名但不加下划线
class User {
private _password: string = ''
get password(): string {
return this._password
}
set password(newPass: string) {
this._password = newPass
}
}
const u = new User()
u.password = 'uouuo' //修改_password
console.log(u.password) //获取_password
八、抽象类
- 抽象类是用来作为子类的基类去使用的,比如说我们创建一个Animal类,再基于Animal类派生出来Cat、Dog类,真正使用的时候呢并不会用Animal类,而是用派生出来的Cat、Dog类。所以Animal本身不具备实例化的需求,可以理解为它就是用来去规范格式的,这种类就很适合作为抽象类来设置。
- 抽象类里可以有抽象/非抽象的属性、方法、存取器。
- 抽象成员必须在抽象类中使用,抽象的属性name不需要初始化,它只是为了让子类在用的时候知道需要实现一个叫name的属性。
- 抽象的方法在抽象类里不能有实现,需要到子类里实现,非抽象方法则需要在抽象类里实现。
abstract class Animal {
abstract name: string
abstract maskSound(): void
move(): void {
console.log('移动')
}
}
class Cat extends Animal {
name: string = '小猫'
maskSound(): void {
console.log('小猫叫')
}
}
九、类实现接口
通过interface来定义类应该具有的行为
interface Animal {
name: string
get sound(): string
makeSound(): void
}
interface B {
age: number
}
//实现Animal和B接口,就是说用Animal和B给类的创建提供规则
class Dog implements Animal, B {
name: string = '小狗'
age: number = 10
get sound(): string {
return 'sound'
}
makeSound(): void {
console.log('makeSound')
}
}
十、泛型类
class MyClass<T>{
public value: T
constructor(value: T) {
this.value = value
}
do(input: T): T {
return input
}
}
const myStr = new MyClass<string>('abc')
myStr.do('def')
网友评论