TS官网演练场:www.typescriptlang.org/zh/play/
一、TypeScript基础类型
1、数字number
const num1: number = 10; // 十进制
const num2: number = 0b0101; // 二进制
const num3: number = 0o17; // 八进制
const num4: number = 0xff; //十六进制
2、字符串string
const str: string = 'str';
3、布尔值boolean
const isBool: boolean = true;
4、null和undefined
-
null和undefined类型一般不会单独使用,一般会用在联合类型中。
-
这两个类型是所有类型的子类型,一般情况下我们可以给其他类型赋值为null和undefined(如果报错的话,可能是tsconfig.json中开启了严格模式)。
const n: null = null;
const u: undefined = undefined;
const v: number | null = null;
5、数组Array
数组有两种写法:
- 数组元素类型后面加上
[] - 泛型数组
Array<数组类型>
const list1: number[] = [1, 2];
const list2: Array<number> = [1, 2];
6、元组Tuple
元组类型表示一个已知元素数量和数组的数组,各元素的类型可以不用相同。
const tuple: [number, string] = [1, '2'];
//也可以使用?表示这个值是可选的
const tuple: [number, string?] = [1];
7、枚举enum
enum是对JavaScript标准类型的一种补充,使用枚举类型可以为一组数值赋予语义化的名字。
枚举值默认从0开始,也可以设置初始值从1开始递增,也可以为每一个名称设置值。
enum Color {
Red = 1,
Green = 3,
Blue = 4,
}
// 我们可以通过Color根据定义的名字获取枚举的数值,也可以根据数值获取枚举值的名字
const myColor: Color = Color.Red;
console.log(myColor, Color.Red, Color[3]); // 1 1 'Green'
8、任意any
对于不确定的类型可以使用any
let value: any = 1;
value = false;
const arr: any[] = [1, false, 'str'];
9、函数void
void表示没有任何类型,一般用来说明函数的返回值不能是null或undefined之外的值(严格模式下只支持返回undefined)
// 没有参数或返回值
function a(): void {
return undefined;
}
// 有参数和返回值,最后一个值设置可选
function fun(a: number, b?: string): number {
return 100;
}
fun(100);
//使用rest
function fun(a: number, b: string, ...rest: number[]): number {
return 100;
}
fun(100, '100', 1, 2);
10、对象object
-
我们可以使用接口定义对象类型
-
严格模式下可以返回undefined,非严格模式下可以返回null和undefined
function func(obj: object): object {
console.log(obj);
return {};
}
func(new Number(1));
func(1); // Error
// 使用接口定义对象
interface Obj {
name: string,
age: number
}
const o1: Obj = {
name: 'name',
age: 3
}
11、 联合类型
联合类型(Union Types)变量的值可以为多种类型中的一种
const a: string | number = 1;
12、类型断言
TypeScript 允许你覆盖它的推断,并且能以你任何你想要的方式分析它,这种机制被称为「类型断言」。
类型断言是一个编译型的语法。
它之所以不被称为「类型转换」,是因为转换通常意味着某种运行时的支持。但是,类型断言纯粹是一个编译时语法,同时,它也是一种为编译器提供关于如何分析代码的方法。
/*
类型断言(Type Assertion): 可以用来手动指定一个值的类型
语法:
方式一: <类型>值
方式二: 值 as 类型 tsx中只能用这种方式
*/
const array = [1, 2, 3];
let result = array.find(item => item > 2) as number;
// 如果不加 as number,result 会报错 “result可能为undefined”
// 加上 as number 覆盖 ts 的推断,表示我断言这是一个数字
result *= 5;
13、类型推断
不推荐使用,最好使用明确的类型注解
TS会在没有明确指定类型的时候进行类型推测
- 定义变量时赋值了,推测为对应的类型
- 定义变量时没有赋值,推断为any类型
14、类型别名type
type myUserName = string | number
let u1: myUserName = 12
let u2: myUserName = '12'
二、接口
1、普通对象
使用接口来定义对象的类型,接口是对对象的状态(属性)和行为(方法)的抽象(描述)。
当我们定义了接口类型的对象之后,不可以多写或少写属性,但是可以设置属性可选?,也可以设置属性只读readonly。
interface obj {
readonly name: string, // readonly设置属性只读
age: number,
sex?: string // ?表示属性可选
}
const o1: obj = {
name: 'name',
age: 3
}
o1.name = 'new-name' // Error
2、函数
/*
接口可以描述函数类型(参数的类型与返回的类型)
*/
interface SearchFunc {
(source: string, subString: string): boolean
}
// 参数名称可以不用一致,但是类型必须一致
const mySearch: SearchFunc = function (source: string, sub: string): boolean {
return source.search(sub) > -1
}
console.log(mySearch('abcd', 'bc'))
3、类
- 一个类可以实现多个接口
- 一个接口可以继承多个接口
interface Alarm {
alert(): any
}
interface Light {
LightOn(): void,
LightOff?(): void
}
interface Sound extends Alarm {
turnOn(): void
}
class Car implements Alarm, Light {
alert() {}
LightOn() {}
}
class SmallCar implements Sound {
alert() {}
turnOn() {}
}
三、泛型
// 如果后续想传入两个string变量,生成string数组,这个方法就不合适了
function myFun(a: number, b: number):number[] {
return [a, b]
}
myFun(1,2)
为了解决这个问题,我们可以使用泛型,在函数中定义泛型,函数调用时指定泛型.
这里的T是一种变量,我们也可以定义其他的变量名,也可以设置多个变量。
function myFun<T>(a: T, b: T):T[] {
return [a, b]
}
myFun<number>(1,2)
也可以在类中使用泛型
class MyClass<T> {
name: T;
constructor(name: T) {
this.name = name;
}
}
const cla = new MyClass<string>('str');
四、进阶
1、函数重载
JavaScript不支持函数重载,但是TypeScript支持了,可以创建多个名称一样,但是参数类型和返回值不同的函数。
function hello(x: string): string;
function hello(x: number): string;
function hello(x: string | number): string {
if (typeof x === 'string') {
return 'string';
}
if (typeof x === 'number') {
return 'number';
}
return '';
}
hello(1);
2、接口继承
Child接口继承自Parent,如果一个变量声明为Child类型,那么要同时具有Parent的特性。
interface Parent {
prop1: string;
prop2: number;
}
interface Child extends Parent {
prop3: string;
}
const p: Child = {
prop1: 'p1',
prop2: 2,
prop3: 'p3',
};
3、类的修饰符
?:属性可选,可以传入这个参数,也可以不穿public:可以在类、子类、实例对象中访问private:只能在类中访问protected:只能在类、子类中访问static:静态属性,通过类来访问,可以被子类继承readonly:只读属性,不可以修改
class Animal {
// ts的语法,用来声明类Animal上存在属性name,是string
name: string;
// 表示该属性可选
type?: string;
// 自动识别为number类型,并设置为默认值,相当于age: number,并且在construct中设置初始值为1
age = 1;
// 默认都是public,可以在类、子类、实例对象中访问
// private表示只能在类Animal中访问,属于类的私有属性
private data?: number[];
// protected:受保护的,只能在Animal类及其子类中使用
protected pData?: string[];
// 静态属性,只能在类内部使用
static sData: string;
// 只读,不可修改
readonly rDate?: string;
constructor(name: string) {
this.name = name;
}
}
class Cat extends Animal {
constructor(name: string) {
super(name);
console.log(this.pData);
}
}
const d = new Animal('dog');
console.log(d.age);
4、类的存取器
class User {
private _password: string = '';
get password(): string {
return this._password + '****';
}
set password(newPassword: string) {
this._password = newPassword;
}
}
const user1 = new User()
console.log(user1.password); // 会调用get方法
5、抽象类
抽象类是作为子类的基类去使用,抽象类本身不具备实例化的这种需求,可以理解为规范了一种格式,我们从抽象类派生出一些子类,通过子类进行实例化。
抽象类通过abstract声明,不可被实例化,内部可以包含抽象属性和方法,也可以包含非抽象属性和方法。
抽象属性不需要被初始化,在子类中被实现(初始化)。
abstract class A {
abstract a: string;
abstract b(): void;
}
class B extends A {
a: string = '1';
b() {
console.log('');
}
}
学习资料: