基础
1. 基础类型
- 常用:boolean、number、string、array、enum、any、void
- 不常用:tuple、null、undefine、never
数组
const numberArr = [1, 2, 3];
const arr: number[] = [1,2,3];
// 除此之外,还可以使用数组泛型
const _arr: Array<number> = [1, 2, 3];
const stringArr: string[] = ['a', 'b', 'c'];
// 如果这个数组里面既存数字又存字符串,如何写
const arr1: (number | string)[] = [1, '2' ,3];
// 除了基本类型的数组,对象类型的数组怎么写
const objectArr: {name: string, age: number}[] = [{name:'a', age:16}]
// 将上面的写法简化下,利用 type alias 类型别名
type User = {name: string, age: number}
const objectArr1: User[] = [{name:'a', age:16}]
2. interface 和 type
-
interface
- 对象interface
- 设置需要存在的普通属性
- 设置可选属性
- 设置只读属性
interface Person { name: string bool?: boolean readonly timestamp: number readonly arr: ReadonlyArray<number> // 此外还有 ReadonlyMap/ReadonlySet } let p1: Person = { name: 'oliver', bool: true, // ✔️️ 可以设置可选属性 并非必要的 可写可不写 timestamp: + new Date(), // ✔️ 设置只读属性 arr: [1, 2, 3] // ✔️ 设置只读数组 } let p: Person = { age: 'oliver', // ❌ 多出来的属性 name: 123 // ❌ 类型错误 } p1.timestamp = 123 // ❌ 只读属性不可修改 p1.arr.pop() // ❌ 只读属性不可修改- 函数 Interface
Interface 还可以用来规范函数的形状。Interface 里面需要列出参数列表返回值类型的函数定义。
interface Func { // ✔️ 定于这个函数接收两个必选参数都是 number 类型,以及一个可选的字符串参数 desc,这个函数不返回任何值 (x: number, y: number, desc?: string): void } const sum: Func = function (x, y, desc = '') { // const sum: Func = function (x: number, y: number, desc: string): void { // ts类型系统默认推论可以不必书写上述类型定义 console.log(desc, x + y) } sum(32, 22) - 对象interface
-
type
type User = { name: string age: number }; type SetUser = (name: string, age: number) => void; function getName(user: User) { return user.name }
相同点
1. 都允许拓展
// interface extends interface
interface Name {
name: string;
}
interface User extends Name {
age: number;
}
// type extends type
type Name = {
name: string;
}
type User = Name & { age: number };
// interface extends type
type Name = {
name: string;
}
interface User extends Name {
age: number;
}
type extends interface
interface Name {
name: string;
}
type User = Name & {
age: number;
}
不同点
- type 可以声明基本类型别名
type s = string
- type 语句中还可以使用 typeof 获取实例的 类型进行赋值
type div = document.createElement('div');
- interface可以合并声明
interface User {
name: string
age: number
}
interface User {
sex: string
}
/*
User 接口为 {
name: string
age: number
sex: string
}
*/
3. enum枚举
enum d1 {
a,
b,
c,
}
enum d1 {
a,
b = 'two',
c = 'three',
}
// 赋值了非数字的,下一个一定要赋值,除非它是最后一个,例如下面这种情况会报错
enum d1 {
a,
b = 'two',
c,
}
4. 泛型 T(Type)
简单说就是:泛指的类型,不确定的类型,可以理解为一个占位符(使用T只是习惯,使用任何字母都行)
- K(Key):表示对象中的键类型;
- V(Value):表示对象中的值类型;
- E(Element):表示元素类型。
function createArray<T>(length: number, value: T): Array<T> {
let result: T[] = [];
for (let i = 0; i < length; i++) {
result[i] = value;
}
return result;
}
createArray<string>(3, 'x'); // ['x', 'x', 'x']
// 第一个T相当于一个变量,调用函数时createArray<string>...相当于给T赋值string类型
5. 类
class Gen {
age: number 变量的类型限制的声明;
constructor(age: number) {
this.age = age;
}
getAge() {
return this.age;
}
}
const gen = new Gen(18);
// 与es6相比,多了age: number 变量的类型限制的声明
继承
class Animal {
age: number
constructor(age: number) {
this.age = age
}
getAge() {
console.log(this.age)
}
}
class Cat extends Animal {
say() {
console.log('miao~')
}
}
const cat = new Cat(18)
cat.getAge() //
cat.say() // miao~
复杂一点的继承
class Animal {
name: string;
constructor(theName: string) { this.name = theName; }
move(distanceInMeters: number = 0) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
class Snake extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 5) {
console.log("Slithering...");
super.move(distanceInMeters);
}
}
class Horse extends Animal {
constructor(name: string) { super(name); }
move(distanceInMeters = 45) {
console.log("Galloping...");
super.move(distanceInMeters);
}
}
let sam = new Snake("Sammy the Python");
let tom: Animal = new Horse("Tommy the Palomino");
sam.move();
tom.move(34);
// 派生类:重写constructor
// 在派生类中,必须调用super
// super相当于指向父类,如果在constructor直接使用super(),想当与调用父类的constructor
公共,私有与受保护的修饰符
- 在typescript中,默认public
- 当成员被标记成private时,它就不能在声明它的类的外部访问,比如这样会报错
- protected修饰符与private修饰符的行为很相似,但protected成员在派生类中仍然可以访问
存取器 get、set
class A {
private _name: string = 'world';
get name(): string {
return this._name;
}
set name(name: string) {
this._name = 'hello' + name
}
}
const a = new A()
console.log(a.name)
a.name = 'Johnny'
console.log(a.name)
// 只是使用a.name时,就会执行get name
// 当给a.name赋值时,相当于调用set name,因此set需要一个参数
// 如果只有get,那么相当于该变量的属性为readonly
6. 函数
函数的返回值
- 有返回值:number、string、boolean
function a(x: number): number { return x } function b(x: number): boolean { return !!x } - 无返回值:void
类型推断
// myAdd has the full function type
let myAdd = function(x: number, y: number): number { return x + y; };
// The parameters `x` and `y` have the type number
let myAdd: (baseValue: number, increment: number) => number =
function(x, y) { return x + y; };
相当于
type Adder = (a: number, b: number) => number;
let myAdd: Adder = function(x: number, y: number) {
return x + y
}
可选参数和默认参数
参数后面加“?”
function buildName(firstName: string, lastName?: string) {
if (lastName)
return firstName + " " + lastName;
else
return firstName;
}
7. 类型推论
最佳通用类型
当需要从几个表达式中推断类型时候,会使用这些表达式的类型来推断出一个最合适的通用类型。例如下面相当于const arr: number[] = [1],因为赋值的数组中只有number这个类型,所以当push一个不是number的值时就会报错
8. 类型兼容性
-
TypeScript结构化类型系统的基本规则是,如果x要兼容y,那么y至少具有与x相同的属性。比如:
interface Named { name: string; } let x: Named; // y's inferred type is { name: string; location: string; } let y = { name: 'Alice', location: 'Seattle' }; x = y; // 虽然可以这样写,但只能获取x.name无法获取x.location但不可以
interface Named { name: string; age: number; } let x: Named; // y's inferred type is { name: string; location: string; } let y = { name: 'Alice', location: 'Seattle' }; x = y; // error // x必须接受一个string属性的name和一个number的age -
比较两个函数
let x = (a: number) => 0; let y = (b: number, s: string) => 0; y = x; // OK x = y; // Error // 若a给b赋值,则a中的每一个参数都能在b中找到对应的参数 (一定是对应的参数,参数名可以随意)个人理解:上面的赋值相当于
let x: (a: number) => number = (b: number, s: string) => 0 // errorlet y: (b: number, s: string) => number = (a: number) => 0 // ok -
类:只有实例的成员会被比较。 静态成员和构造函数不在比较的范围内
9. 高级类型
交叉类型(&)
交叉类型说简单点就是将多个类型合并成一个类型
T & U
interface a {
name: string;
age: number;
}
interface b {
tall: number
}
const people: a & b = {
name: 'wong',
age: 18,
tall: 176
}
联合类型(|)
联合类型的语法规则和逻辑 “或” 的符号一致,表示其类型为连接的多个类型中的任意一个
T | U
type InnerType = 'default' | 'primary' | 'danger'
类型别名
type InnerType = 'default' | 'primary' | 'danger'
interface Button {
type: InnerType
text: string
}
类型索引 keyof
interface Button {
type: string
text: string
age: number
}
type ButtonKeys = keyof Button
// keyof相当于Object.keys
// type ButtonKeys = 'type' | 'text' | 'age'
interface a {
type: ButtonKeys;
}
let b: a = {
type: 'age'
}
类型约束(extends)
type BaseType = string | number | boolean
// 这里表示 copy 的参数
// 只能是字符串、数字、布尔这几种基础类型
function copy<T extends BaseType>(arg: T): T {
return arg
}
类型映射(in)
interface a {
text: string;
name: string;
}
type onlyRead<T> = {
readonly [P in keyof T]: T[P];
}
const c: onlyRead<a> = {
text: 'tt',
name: 'nn'
}
理解:
// keyof T得到 'text' | 'name'
// p通过in去遍历'text' | 'name'
// 首次遍历p就是'text', 所以T['text']就是string,所以就是text: string --> readonly text: string
// 最终得到的就是
interface _a {
readonly text: string;
readonly name: string;
}