TypeScript 学习笔记
基本数据类型
- 布尔值(boolean)
const is: boolean = true;
- 数值(number)
const num: number = 1;
- 字符串(string)
const str: string = 'Hello World';
- 数组(Array)
const numList: number[] = [0, 1, 2, 3, 4]; // 数值型数组 const strList: string[] = ['Hello', 'World']; // 字符串数组
- 元祖(Tuple)
元组表示一个已知元素数量和类型的数组, 各元素的类型不必相同const tuple: [number, string, boolean, number] = [0, 'Hello World', true, 1];
- 枚举(enum)
// 自带默认值索引, 从 0 开始 enum LANGUAGE_ENUM { JAVA, JS, TS, } let language: LANGUAGE_ENUM = LANGUAGE_ENUM.JAVA; console.log(language); // 0 language = LANGUAGE_ENUM.JS; console.log(language); // 1 language = LANGUAGE_ENUM.TS; console.log(language); // 2 // 自动递增, 仅对数值型赋值有效 enum FRAMEWORK_ENUM { VUE = 1, REACT, ANGULAR, } let framework: FRAMEWORK_ENUM = FRAMEWORK_ENUM.VUE; console.log(framework); // 1 framework = FRAMEWORK_ENUM.REACT; console.log(framework); // 2 framework = FRAMEWORK_ENUM.ANGULAR; console.log(framework); // 3 enum JS_FRAMEWORK_ENUM { VUE, REACT = 3, ANGULAR, } let framework: JS_FRAMEWORK_ENUM = JS_FRAMEWORK_ENUM.VUE; console.log(framework); // 0 framework = JS_FRAMEWORK_ENUM.REACT; console.log(framework); // 3 framework = JS_FRAMEWORK_ENUM.ANGULAR; console.log(framework); // 4 // 手动赋值 enum IDE_ENUM { VS = 'vs code', WS = 'web storm', ST = 'sublime text', } let framework: IDE_ENUM = IDE_ENUM.VS; console.log(framework); // vs code framework = IDE_ENUM.WS; console.log(framework); // web storm framework = IDE_ENUM.ST; console.log(framework); // sublime text framework = 'HBuilder' // error
- 空值(null)
const money: null = null;
- 未定义(undefined)
const girlFriend: undefined = undefined;
- 对象(object)
const obj: object = {};
- 任意类型(any)
一般用于无法确定数据类型时定义数据, 可以和除void
和never
类型外的数据兼容let something: any = 'Hello World'; something = 12138; something = false;
- void
表示没有任何类型, 与 any 相反. 一般用于定义函数没有返回值function fn(): void(){}
- Never
never类型表示的是那些永不存在的值的类型
类型定义
// 普通的定义就是 变量: 类型
const str: string = 'Hello World';
// 兼容性定义, 定义多个类型
let params: number | string | undefined;
console.log(params); // undefined
params = 0;
console.log(params); // 0
params = 'Hello World';
console.log(params); // Hello World
// 函数
function fn(param1: number, params2: string): boolean { return true;}
接口 interface
使用接口做数据的类型定义
上面的 string
, number
只能对简单的数据做类型校验, 如果要校验一些复杂的对象, 就必须使用 interface, 自己定义数据的结构已经字段的类型
// 定义一个 People 的接口
interface People {
name: string;
age: number;
girlFriend?: People; // 可选参数, 定义 People 类型的数据是 girlFriend 可有可无, 有的时候一定要是 People 类型
}
const eno: People = {
name: 'eno',
age: 18,
}
console.log(eno); // { name: 'eno', age: 18 }
const anni: People = {
name: 'anni',
age: 18,
}
const enoPlus: People = {
name: 'eno plus',
age: 18,
girlFriend: anni,
}
console.log(enoPlus); // { name: 'eno plus', age: 18, girlFriend: { name: 'anni', age: 18 } }
接口的继承
接口可以使用 extends
继承另一个接口, 从而得到其他接口已经定义好的字段, 继承过来之后可以进行修改或直接使用
interface People {
name: string;
age: number;
}
interface Man extends People {
girlFriend?: Woman
}
interface Woman extends People {
boyFriend?: Man
}
const eno: Man = {
name: 'eno',
age: 18,
}
const anni: Woman = {
name: 'anni',
age: 18,
boyFriend: eno,
}
console.log(anni); // { name: 'anni', age: 18, boyFriend: { name: 'eno', age: 18 } }
泛型
有时候一些组件或代码库, 在设计时并不知道使用时会有什么类型的数据, 但是有想要做数据类型定义, 这是后可以使用泛型.
代码库在设计的时候可以定义接收一个或多个数据类型, 用这些数据类型去做类型定义, 在代码被使用的时候用户根据自身情况,
传入对应的数据类型
函数
function fn<T, P>(params: T): P {}
const num:number = fn<string, number>('Hello world');
接口
interface IState<T> {
something: T
};
const state: IState<number> = { something: 123 };
类
class People<T> {
name?: T;
constructor(name: T) {
this.name = name;
}
}
const eno = new People<string>('eno');
console.log(eno); // { name: 'eno' }
类 class
私有方法和属性
TS 类的是有和 JS 中 ES6 的使用语法差不多, 但是 TS 中的属性和方法可以加上 private
变成私有的.
私有的属性和方法只能在类内部使用, 使用类的实例也无法调用
class People {
public name: string; // 公共属性, public 可以省略
private age: number; // 私有属性, 外部无法访问, 只有类内部可以访问
private job?: string; // 可选的私有属性
constructor(name: string, age: number, job?: string) {
this.name = name;
this.age = age;
this.job = job;
}
// 共有方法, public 可以省略
public selfIntroduction() {
// 类内部调用私有属性
console.log(`My name is ${this.name}, ${this.age} years old`);
// 类内部调用私有方法
this.getJob();
}
// 私有方法, 外部无法访问, 只有类内部可以访问
private getJob() {
if(this.job) {
console.log(`I am a ${this.job}`)
} else {
console.log(`I not a job`);
}
}
}
const eno = new People('eno', 18, 'programmer');
console.log(eno.name); // eno
eno.selfIntroduction(); // My name is eno, 18 years old \n I not a job
// 试图调用私有方法和属性
console.log(eno.age); // error
console.log(eno.job); // error
eno.getJob(); // error
readonly 修饰符
readonly
修饰符也是 TS 相对于 JS 特有的, 使用 readonly
的属性, 必须在声明或构造函数中赋值, 之后不能更改
class People {
readonly id:string;
constructor(id: string) {
this.id = id;
}
}
const eno = new People('9527');
console.log(eno.id); // `9527`
eno.id = '12138'; // error
抽象类
抽象类做为其它派生类的基类使用. 它们不会直接被实例化.
抽象类中的抽象方法不包含具体实现并且必须在派生类中实现, 用于规范派生类中需要有的属性和方法
abstract关键字是用于定义抽象类和在抽象类内部定义抽象方法。
abstract class People {
// 声明一个抽象属性和方法
abstract name: string;
abstract selfIntroduction():void;
// 同样也可以定义普通的方法
print() {
console.log(`I am People class`);
}
}
class Man extends People {
name: string; // 必须有 People 定义的 name
constructor(name: string) {
super();
this.name = name;
}
// 必须试下 People 定义的 selfIntroduction
selfIntroduction() {
console.log(`My name is ${this.name}`);
}
}
const eno = new Man('eno');
console.log(eno.name); // eno
eno.selfIntroduction(); // My name is eno
eno.print(); // I am People class
// 实例化虚拟类会报错
new People(); // error
命名空间
namespace A {
// 使用 export 的才能被外部使用
export function print() {
console.log('print A');
get();
}
// 没有 export 的只能在模块内部使用
function get() {
console.log('get A');
}
}
namespace B {
export function print() {
console.log('print B');
}
export function get() {
A.get(); // error
}
}
A.pint(); // print A \n get A
B.print(); // print B
A.get(); // error
需要在多文件中使用命名空间只需要把不同的命名空间分开写在对应的文件中, 然后使用 export
暴露出来即可, 跟其他东西的模块化一样
学习笔记, 可能会有错误
不定期更改, 欢迎指正