是什么?
TypeScript
是 JavaScript
的类型的超集,扩展了 JavaScript 的语法,支持ES6
语法(记住这张图)
基本语法
数据类型
- boolean(布尔类型)
- number(数字类型)
- string(字符串类型)
- array(数组类型)
- tuple(元组类型:各元素的类型不必相同)
- enum(枚举类型)
- any(任意类型)
- null 和 undefined 类型
- void 类型
- never 类型
- object 对象类型
//boolean
let flag:boolean = true;
//number
let num:number = 123;
//string
let str:string = 'this is ts';
//array
let arr:string[] = ['12', '23']; //定义字符串数组
let arr:number[] = [10,20]; //定义数字数组
let arr:Array<number> = [1, 2]; //泛型 Array<元素类型>
//tuple
let tupleArr:[number, string, boolean];
tupleArr = [12, '34', true]; //ok
typleArr = [12, '34'] // no ok
//enum
enum Color {Red, Green, Blue = 100}
let c: Color = Color.Green; //如果没有给值,返回就是下标 1
let d:color = Color.Blue; //有值的话返回就是100
//any
let num:any = 123;
num = 'str';
num = true;
//null 和 undefined
let num2:undefined
let num3:null
num3 = null
//viod 没有return返回值
function hello(): void {
alert("Hello Runoob");
}
//never 一般用来指定那些总是会抛出异常、无限循环
let a:never;
a = 123; // 错误的写法
a = (() => { // 正确的写法
throw new Error('错误');
})()
function error(message: string): never {
throw new Error(message); // 抛出异常
}
// object
let obj:object;
obj = {name: 'Wang', age: 25};
函数
函数类型取决于return
返回值类型
//声明方式 :当存在函数重载时,只能使用方式一的形式
// 方式一
type LongHand = {
(a: number): number;
};
function func(a: number):number{
return a
}
// 方式二
type ShortHand = (a: number) => number;
//有可选参数
const add = (a: number, b?: number) => a + (b ? b : 0)
function add(a: number, b?: number):number{
if(b){
return a+b
}else{
return a
}
}
// 剩余参数
const add = (a: number, ...rest: number[]) =>
rest.reduce(((a,cur) => a + cur), a)
// 例如我们有一个add函数,它可以接收 string类型的参数进行拼接,
//也可以接收 number 类型的参数进行相加
function add (arg1: string, arg2: string): string
function add (arg1: number, arg2: number): number
// 在实现上我们要注意严格判断两个参数的类型是否相等,
//而不能简单的写一个 arg1 + arg2
function add (arg1: string | number, arg2: string | number) {
if (typeof arg1 === 'string' && typeof arg2 === 'string') {
return arg1 + arg2
} else if (typeof arg1 === 'number' && typeof arg2 === 'number') {
return arg1 + arg2
}
}
类
定义与继承
class Animal {
// 字段
name:string;
// 构造函数
constructor(n:string) {
this.name = n
}
// 方法
say():void {
console.log(`Animal name is ${this.name}`);
}
doPrint():void {
console.log("父类的 doPrint() 方法。")
}
}
// 继承 extends
class Dog extends Animal {
color:string;
construtor(n:string){
super(n); //继承父类属性
this.color = '默认颜色'
}
bark() {
console.log('Woof! Woof!');
}
//重写父类方法
doPrint():void {
super.doPrint() // 调用父类的函数
console.log("子类的 doPrint()方法。")
}
}
const dog = new Dog();
console.log(dog.name);
console.log(dog.color)
dog.say();
dog.bark();
修饰符
公共
public
:可以自由的访问类程序里定义的成员
私有private
:只能够在该类的内部进行访问
受保护private
:除了在该类的内部可以访问,还可以在子类中仍然可以访问readonly
:只读属性必须在声明时或构造函数里被初始化,不能被修改
静态属性: static
—访问这些属性需要通过 类型.静态属性 的这种形式访问
class Square {
static width = '100px'
}
console.log(Square.width) // 100px
抽象类 :不能被创建,是用来给子类继承的模板,关键词abstract
//定义抽象类 abstract关键词的方法子类一定要有!
abstract class Animal {
abstract makeSound(): void;
move(): void {
console.log('roaming the earch...');
}
}
// 被子类继承
class Cat extends Animal {
makeSound() {
console.log('miao miao')
}
}
const cat = new Cat()
cat.makeSound() // miao miao
cat.move() // roaming the earch...
多态:例如父类定义一个方法,子类继承可以各有表现
class Animal {
eat():void{}
}
// 被子类继承
class Cat extends Animal {
eat():void{
console.log('猫咪吃鱼')
}
}
class Dog extends Animal {
eat():void{
console.log('狗狗吃骨头')
}
}
接口
接口的作用就是为为这些类型命名和为你的代码或第三方代码定义一个约定,关键词interface
属性接口
interface User {
name: string
age: number
}
const getUserName = (user: User) => user.name // 报错,缺少age属性
//或者把age变成可选参数
interface User {
name: string
age?: number
}
函数接口
interface sum{
//小括号对参数的约定,冒号后面是对return约束
(num1:number,num2:number):number
}
var total:sum = function(num1:number,num2:number):number{
return num1 + num2
}
console.log(total(30,20))
数组,对象接口
//数组 :中括号对索引约束,后面是对元素约束
interface arrItf{
[index:number]:number
}
//对象 : 中括号是对键约束,后面是对值约束
interface objItf{
[index:string]:any
}
类接口
// 如果有继承,先继承后接口
interface classItf{
color:string;
eat():viod;
}
class Animal{
name:string;
constructor(n:string){
this.name = n
}
}
class Dog extends Animal implements classItf{
color:string;
construtor(n:string){
super(n); //继承父类属性
this.color = 'black'
}
eat():void{
console.log('吃骨头')
}
}
接口继承
interface Father {
color: String
}
interface Mother {
height: Number
}
interface Son extends Father,Mother{
name: string
age: Number
}
// 定义的 类要符合以上接口约定
class Childer implements Son{
color: string;
height: number;
name: string;
age: string;
...
}
泛型
通过传入内容决定类型,通过<>
的形式进行表述
函数
function returnItem<T>(para: T): T {
return para
}
returnItem<number>(10)
returnItem<string>('hello')
// 多个类型参数,元组
function swap<T, U>(tuple: [T, U]): [U, T] {
return [tuple[1], tuple[0]];
}
swap([7, 'seven']); // ['seven', 7]
类
class Stack<T> {
arr: T[] = []
pushFn(item: T) {
this.arr.push(item)
}
getFn():T {
return ths.arr[1] //返回数组第二个值
}
}
let obj = new Stack<number>()
obj.pushFn(20);
obj.pushFn(30);
obj.getFn()
接口
//方式一
interface config{
<T>(val:T):T
}
let getData:config = function<T>(val:T):T{
return val
}
//方式二
interface config<T>{
(val:T):T
}
function getData<T>(val:T):T{
return val
}
let getStringData:config<string> = getData;
let getNumberData:config<number> = getData;
模块
export {xx,xx,xx} => import {xx,xx,xx} from '...'
export default {xx1,xx2,xx3} => import a from '...'
a.xx1
a.xx2
a.xx3
命名空间
内部模块又叫做命名空间:命名空间一个最明确的目的就是解决重名问题
关键词:namespace
//全部暴露
export namespace A {
interface ISomeInterfaceName { }
class SomeClassName { }
...
}
namespace B {
//局部暴露
export interface InterfaceName { }
export class SomeClassName { }
...
}
装饰器
关键词 @xxxxx
,Object.defineProperty的语法糖,本质是一个函数
装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上
是一种在不改变原类和使用继承的情况下,动态地扩展对象功能
参考文章
//方法装饰器 不改变原有代码基础上,添加新功能
// 例如,计算1相加到10000000000的计算过程
// 原有代码:相加
// 装饰器功能:计算时间
function logMethod(p:any){
return function(target:any,methodName:any,desc:any){
console.log(target); //构造函数 / 原型对象
console.log(methodName); // 方法名
console.log(desc); // 方法的引用
console.log(p); //参数
// 重写方法
let oldMrthod = desc.value;
desc.value = function(){
//获取开始时间戳
let start = new Date().getTime()
//执行原来代码
let mysum = oldMrthod()
// 获取结束时间
let end = new Date().getTime()
// 计算用时
let ret = end - start / 1000;
console.log(`一共用时是${ret}秒`)
return mysum //返回计算结果
}
}
}
class Myclass{
@logMethod('')
sum():number{
let sum = 0;
for(let i= 0;i<10000000000;i++){
sum+=1
}
return sum
}
}