TypeScript的定义
TypeScript是js的一个超集(superset),而且拥有类型的机制,而且不能在浏览器直接执行,要编译成js才能执行。
超集(superset)释义:
es6就可以说是es5的一个超集,es6兼容了es5所有的语法,还提出了自己新有的独特的语法特性,意思着es6是es5的超集。所以ts页拥有js的基础特性。
ts静态类型
// js类型 js的类型是动态类型
let a = 123;
a = '123'
//ts类型 ts的类型的静态类型
let b = 123;
b = '123'; // error 会报错 b存储的数字类型,未来存储的也要是数字类型 '123'这个字符串 没办法存储到b
// ts定义类型的写全的写法
let b:number = 123
b = 234
TypeScript带来的优势
- 相对js,ts的静态类型使得我们在编写代码时候,帮我们更容易定位发现一些潜在的问题。
- ts可以给我们更好的代码提示。
- 通过静态类型的定义,让我们更好的阅读代码,代码语义更清晰易懂。
intarfase Point {x:number, y:number}
function tsDemo(data: Point) {
return Matg.sqrt(data.x ** 2 + data.y ** 2)
}
静态类型的深度理解
我们看见ts的一个静态类型,不仅仅意味着这个变量的类型不能修改,还意味这个变量上属性和方法基本上页锁定了。
类型的基础和对象类型
ts中类型分为基础类型和对象类型
基础类型:
null、undefined、symbol、boolean、void、string、number
对象类型:
函数类型 数组类型 类类型 对象类型
// 基础类型 : null undefined symbol boolean void
const count: number = 123;
const teacherName: string = 'yuzhicheng';
// 对象类型
const obj: {
name: string;
age: number;
} = {
name: 'yzc',
age: 22
};
// numbers 必须是数字类型的数组
const numbers: number[] = [1, 2, 3];
class Person {}
// dell 必须是一个 Person类的对象
const dell: Person = new Person();
// getTotal 是一个函数 返回值是一个数组
const getTotal: () => number = () => {
return 123;
};
类型注解 and 类型推断
类型注解(type annotation):
我们告诉ts变量是什么类型。
let count:number
count = 123
类型推断(type inference):
ts会自动去尝试分析变量的类型
let countInference = 123;
如果ts 能自动分析变量类型,我们就不用做类型注解,如果不能分析变量类型,我们就需要使用类型注解。 写ts代码就是需要每一个变量、每一个对象属性、它们的属性都是固定的。可以用类型推断就用类型推断,不能推断就能用类型注解
函数相关类型
function add(first: number, second: number): number {
return first + second;
}
// :void 定义了函数没有返回值
function sayHello(): void {
console.log('hello');
}
// never 定义了函数永远不能执行到最后 完全执行完 也代表没有返回值
function errorEmitter(): never {
throw new Error();
console.log(123);
}
// 函数解构的语法
function addfunc({ first, secound }: { first: number; secound: number }) {
return first + secound;
}
复习
基础类型:
boolean number string void undefined symbol null
定义变量和对变量赋值分开不能进行类型推断
// 这种情况不能类型推断出 count 是数字类型
let count;
count = 123;
对象类型:
{}, Class , function , []
其他例子
// 两种定义函数类型的方式
const func1 = (str:string) => {
return parseInt(str,10)
}
//定义函数体
const func2: (str: string) => number = str => {
return parseInt(str, 10);
};
//可能是两种类型 有可能是number 也有可能是string
let temp: number | string = 123;
temp = '456'
数组和元组
数组的注解
// 定义一个数组 元素内容必须是数字类型
const numberArr: number[] = [12, 3];
// 定义一个数组 元素可能是个数字 或者 字符串
const numOrStrArr: (string | number)[] = [12, '3'];
// 定义一个数组 子元素是个对象
const objArr: { name: string; age: number }[] = [
{
name: 'dell',
age: 22
}
];
// 上面写法 过于繁琐 我们可以定义一个类型别名(type alias) 来实现
type User = { name: string; age: number };
const obj2Arr: User[] = [
{
name: 'dell',
age: 22
}
];
元祖
元祖能帮助我们约束固定长度 切每个数组元素的类型
// 元祖 tuple
/**
* 假设我们需要的是一个数组 且数组里面永远只有三个元素 类型固定
* 这时候数组不能帮我们约束这种类型,ts提供了元组的类型
*/
const teacherInfo: (number | string)[] = [1, 'male', 18];
// 元组 tuple
const teacherInfo2: [string, string, number] = ['dd', 'dd', 2];
// 元组和数组的结合
// 使用场景 csv Excel导出的文件格式
const teacherlist: [string, string, number][] = [
['dd', 'dd', 19],
['dd', 'dd', 19],
['dd', 'dd', 19],
['dd', 'dd', 19]
];
Interface 接口
接口只是在我们开发过程中,ts帮我们做语法提示和校验的工具,编译成js代码的时候会剔除 没有体现。
类型别名 和 接口的区别:
ts 规范中 我们能用interface 接口 去表诉一个类型 就尽量用interface 实在不行我们才去用alias 类型别名
// 可以直接代表一个基础类型 接口不可以
type Person = string
// 我们可以用interface 定义通用的类型 。
// 有通用型的类型集合 我们可以用 interface 去表现出来
interface Person {
name: string;
age?: number; // 表示可有可无 可选参数
[propName: string]: any; // 表示 Person 这个类型集合 还可以有其他属性 数组的名字是个字符串就行 类型是any
say(): string; // 表示这个集合 有个say的方法 返回值是个 string
}
// 类型 别名
type Person1 = {
name: string;
};
const getPersonName = (person: Person) => {
console.log(person.name);
};
const setPersonName = (person: Person, name: string) => {
person.name = name;
};
const person = {
name: 'name',
sex: 'male',
say() {
return '';
}
};
getPersonName(person);
// getPersonName({
// name:'yzc',
// sex:'3' //err ts 在对字面量赋值的时候会强校验
// )
setPersonName(person, 'les');
// 类去应用一个接口
// 类要应用一个接口 就必须要有 接口里面定义的方法 和属性
class User implements Person {
name = 'dell';
say() {
return 'hellp';
}
}
// 接口互相之间实现继承
interface Teacher extends Person {
teach(): string;
}
// interface定义一个函数类型
interface SayHi {
(str: string): string;
}
const sayhi: SayHi = str => {
return 'hi';
};
类的定义与实现
类的继承
extends关键字实现类的继承 当我们重写类的方法 可以用super 关键字去调用父类中被重写的那个方法。
class Person {
name = 'yzc';
getName() {
return this.name;
}
}
// 类实现继承
class Teacher extends Person {
getTeacher() {
return 'Teacher';
}
getName() {
// 类继承的时候 我们重写了getName 方法 可以用super 关键字 调用父类的getName 方法
return super.getName() + 'lee';
}
}
类中的访问类型和构造器
public:
公开的,允许在类的内外被调用。
private:
私有的,允许在类内被调用。
protected:
受保护的,允许在类内 及 继承的子类中使用。
constructor 构造器
class Person {
// 传统写法
// public name: string;
// // 类在创造实例的时候被执行
// constructor(name: string) {
// this.name = name;
// }
// 简化写法
constructor(public name: string) {}
}
const person = new Person('dell');
console.log(person.name);
class Teacher extends Person {
// 当父类有contructor 方法 子类也有contructor 子类必须要用super 去实现父类的 的contractor
// 子类 要使用 contractor 构造器 不管父类有没有 contractor 都必须要用 super()
constructor(public age: number) {
super('yzc');
}
say() {
console.log(this.name);
}
}
const teacher = new Teacher(12);
teacher.say();
静态属性 setter getter
**
* getter对私有属性 做加密 或者其他处理再对外使用
* setter 对外暴露 一个 对 私有属性的写入 我们可以在
* setter 创建的方法里面做处理
*/
class Person {
constructor(private _name: string) {}
// getter
get name() {
return this._name + 'lee';
}
// setter
set name(name: string) {
const realName = name.split(' ')[0];
this._name = realName;
}
}
const person = new Person('dell');
// get的特性 不需要写 方法的 调用 getName
console.log(person.name);
person.name = 'yzc lee';
console.log(person.name);
static 静态属性
静态属性 把方法或者属性 挂在类上 而不是实例上
静态属性 实现单例模式
// 单例模式 一个类永远只有一个实例
class Demo {
// 私有的静态属性
private static instance: Demo;
// 要实现单例模式 就不允许 外部 通过new 关键字实例化
private constructor(public name: string) {}
// 静态属性 把方法 挂在类上 而不是实例上
static getInstance(name) {
// return new Demo();
if (!this.instance) {
this.instance = new Demo(name);
}
return this.instance;
}
}
const demo1 = Demo.getInstance('yzc');
const demo2 = Demo.getInstance('sxy');
console.log(demo1.name);
console.log(demo2.name);
抽象类
readonly 关键字 限制公有属性 只能读不能改
抽象类 abstract
很多类 有相同的通性 我们就可以用抽象类 把这些通性 抽象出来
abstract class Geom {
// 如果 这些 类 的 getArea 的实现都是不一样的 我们可以 抽象 这个方法
// 抽象 方法 意味者这个方法的具体实现是抽象 的 不能直接去写它的实现 只能去定义它
abstract getArea(): number;
// 页可以写一些 属性和方法的具体实现
getType() {
return 'Geom';
}
width: number;
}
// 抽象类 只能被继承 不能被实例
// 子类继承了 抽象类 必须要去实现它的抽象方法
class Cirtcle extends Geom {
getArea() {
return 134;
}
}
class Square {}
class Triangle {}