一些基本使用笔记
一些注意点,不全
使用
- 在ts文件中如果没有
typescript
语法代码,是可以直接在html文件中引用并且运行的
- ts 中使用的关键字
let
在编译成 js 的时候会变成var
变量
如果声明变量的时候直接赋值,TS 可以自动检测变量的类型(即使不指定)
1 2 3
| let xm = '小明';
xm = 18; ❌
|
可以在声明的时候使用字面量指定类型,后面就不能改了(类似于常量)
1 2 3
| let xm: 'xm'; xm = 'zs'; ❌ xm = 'xm'; ✔️
|
可以使用 |
来声明多个类型(联合类型)
1 2 3 4 5 6 7
| let xm: 'male' | 'female' xm = 'male' xm = 'female'
let zs: boolean | string zs = true zs = 'zs'
|
在声明变量时不指定类型,则默认是any
类型,也可以指定any
类型,但是不好。必要时,使用unknown
类型来代替any
类型
unknown
在定义的时候和any
一样,可以随便值,但是不能将自己的值直接赋给别的变量(除非对方是 any)。
1 2 3 4 5 6 7 8
| let xm: unknown; xm = 18; xm = true; xm = 'xm'; let zs: string; zs = xm; ❌
if (typeof xm === 'string') { zs = xm; }
|
类型断言,用来告诉解析器变量的实际类型。有两种写法:
- 变量 as 类型
- <类型>变量
1 2 3
| zs = xm as string zs = <string>xm
|
never
类型,表示永远不会有返回值(如抛出异常)
1 2 3
| function err(): never { throw new Error('错错错...') }
|
- 变量也可以是
never
,即使是any
也不能赋值给never
- 和
void
的区别是,void
是没有返回值,不过可以做其他事情,never
里面是无法到达的事情,如死循环
在声明对象的时候可以指定里面的属性,属性后面加?
表示当前属性可选
1 2
| let xm: {name: string, age?: number}; xm = {name: 'xm'}; ✔️
|
也可以指定任意类型的属性
1 2
| let xm: { name: string; [prop: string]: any } xm = { name: 'xm', age: 18, gender: 'male' }
|
数组类型,有两种方式:
- 变量: 类型[]
- 变量: Array<类型>
1 2 3 4
| let array_1: string[] array = ['zs', 'ls', 'xm'] let array_2: Array<number> array_2 = [1, 2, 3]
|
元组(tuple),固定长度的数组:
- 变量: [类型, 类型, 类型]
1 2
| let array: [string, number, boolean] array = ['xm', 18, true]
|
枚举(enum):
1 2 3 4 5 6
| enum Gender { Male = 0, Female = 1 } let xm: { name: string; Gender: Gender } xm = { name: 'xm', grnder: Gender.Male }
|
合并
1 2
| let xm: { name: string } & { age: number } xm = { name: 'xm', age: 18 }
|
类型别名,用户可以创建自己想要的类型,然后给它取个名字便于调用
1 2 3 4
| type myType = 1 | 2 | 3 | 4 | 5; let age: myType; age = 1; ✔️ age = 6; ❌
|
类
其中主要有:属性 和方法
基本
直接定义的属性是实例属性,需要实例化后访问。static
为静态属性,通过类直接访问。readonly
表示只读属性,可以单独使用,也可在static
后面使用
1 2 3 4 5 6 7 8 9
| class Person { name: string = 'xm' static age: number = 18 readonly gender: string = 'male' static readonly status: string = 'good' } let xm = new Person() xm.name Person.age
|
构造函数
之所以称为构造函数,是因为实在对象创建时(实例化)调用的
1 2 3 4 5 6 7 8 9 10 11 12
| class Dog { name: string age: bumber constructor(name: string, age: number) { ;(this.name = name), (this.age = age) } bark() { console.log('wang~wang~~') } } const dog_1 = new Dog('tom', 2)
|
继承
1 2 3 4 5 6
| class LittleDog extends Dog { bark() { console.log('hahaha') } }
|
- 继承会获得父类的所有属性和方法
- 在子类中有和父类相同名字的方法,就叫做重写
super
在继承的时候,子类想继承父类的属性,又想添加另外的属性,就得用super()
来调用父类的构造函数,并且传入想要继承的属性
1 2 3 4 5 6 7
| class LittleDog extends Dog { kind: string constructor(name: string, kind: string) { super(name) this.kind = kind } }
|
抽象类
abstract
开头,抽象类不能用于创建对象,专门用来被继承的
抽象类中有抽象方法,抽象方法必须在抽象类中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| abstract class Animal { name: string; constructor(name: string) { this.name = name } abstract hello():void {} } class Dog extends Animal { hello() { console.log('wangwang'); } } class Cat extends Animal { hello() { console.log('miaomiao'); } } const fish = new Animal(); ❌ const dog = new Dog(); ✔️ dog.hello();
|
接口
接口用来定义一个类的结构,规定里面要包含的内容。接口可以重复声明,不能有实际的值
1 2 3 4 5 6 7 8
| interface theInter { name: string age: number } interface theInter { gender: string hello(): void }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const obj: theInter = { name: 'xm', age: 18, gender: 'male', hello() { console.log('hello') } }
class Male implements theInter { name: string age: number gender: string constructor(name: string, age: number, gender: string) { ;(this.name = name), (this.age = age) this.gender = gender } hello() { console.log('hello') } }
|
- 在对象中用接口时,接口可以当成一个类型,这是
interface
关键字可以和type
关键字互换
属性封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Person { public _name: string private _age: number protected _gender: string constructor(name: string, age: number) { this._name = name this._age = age } getName() { return this._name } setName(value: string) { this._name = value } }
|
在 TS 中,存取器有另外的写法
1 2 3 4 5 6
| get name() { return this._name; } set name(value: string) { this._name = value }
|
这样写,在实例化之后,和调用属性时一样的写法
1 2 3 4
| const xm = new Person('xm', 18, 'male') xm._name xm.name xm.name = 'zs'
|
泛型
在声明函数或者时类的时候,如果不知道用什么类型,就可以使用泛型。等调用的时候再根据参数指定
1 2 3 4 5
| function fn<T>(a: T): T { return a } let result_1 = fn(10) let result_2 = fn<string>('hello')
|
可以有多个泛型
1 2 3
| function fn<T, U>(a: T, b: U): T { return a }
|
泛型还可以继承于接口
1 2 3 4 5 6
| interface Inter { length: number } function fn<T extends Inter>(a: T): number { return a.length }
|
1 2 3 4 5 6 7
| class MyClass<T> { name: T constructor(name: T) { this.name = name } } const myclass = new MyClass<string>('xm')
|