一份不可多得的TypeScript系统入门整理

2021-07-29 12:39:32 浏览数 (1)

TypeScript.png

TypeScript开发

全局安装typescript,使用安装命令可以使用npm也可以使用yarn

image.png

代码语言:javascript复制
npm install typescript -g

yarn global add typescript

demo.ts

代码语言:javascript复制
function jeskson() {
 let web: string = "hello world"
 console.log(web)
}

jeskson()

// tsc
tes demo.ts
node demo.js

image.png

image.png

代码语言:javascript复制
npm install -g ts-node

数据类型

  • TS的数据类型
代码语言:javascript复制
// ES6的数据类型:
基本数据类型:Boolean,Number,String,Symbol,undefined,null

引用类型:Array,Function,Object

// TS的数据类型,增加
void,any,never,元组,枚举,高级类型

类型注解:

代码语言:javascript复制
let hello : string = 'Hello TypeScript'

原始类型

代码语言:javascript复制
let bl: boolean = true
let num: number = 123
let str: string = "123"

数组泛型

代码语言:javascript复制
let arrType: Array<number> = [0, 1, 2, 3, 5];
let arrType1: Array<string> = ['0', '1', '2', '3', '5'];
let arrType2: Array<any> = [1, '1', 2, 's', true];

用接口表示数组

代码语言:javascript复制
interface Person{
  name: string;
  age: number;
}
interface NumberArray {
       [index:number]: Person;         
}
let arrType3: NumberArray = [{name:'张三',age: 20}]
let arrType4:Array<Person> = [{name:'张三',age: 20}]
let arrType5:Person[] = [{name:'张三',age: 20}]

类数组

类数组(Array-like Object)不是数组类型:

代码语言:javascript复制
function sum() {
    let args: number[] = arguments;
}

// index.ts(2,7): error TS2322: Type 'IArguments' is not assignable to type 'number[]'.
//   Property 'push' is missing in type 'IArguments'.

function sum() {
    let args: IArguments = arguments;
}

元组类型

代码语言:javascript复制
let tuple: [number, string] = [0, '1']
// 此时,如果改变数组的元素类型或添加元素数量,编辑器都会报错
// TS允许向元组中使用数组的push方法插入新元素(但不允许访问)

函数

函数声明(Function Declaration)和函数表达式(Function Expression)

代码语言:javascript复制
// 函数声明(Function Declaration)
function sum(x, y) {
    return x   y;
}

// 函数表达式(Function Expression)
let mySum = function (x, y) {
    return x   y;
};
代码语言:javascript复制
// 函数声明的类型定义
function sum(x:number,y:number):number{
       return x y  
}
// 输入多余的或者少于要求的参数,是不被允许的

// 函数表达式
let mySun = function(x:number,y:number):number{
      return x   y  
}

用接口定义函数的形状

代码语言:javascript复制
interface SearchFunc{
       (source:string,subString:string):boolean
}    

let mySearch:SearchFunc;
mySearch = function(source: string,subString:string){
     return source.search(subString) !== -1  
}

与接口中的可选属性类似,我们用 ? 表示可选的参数:

代码语言:javascript复制
function buildName(firstName: string, lastName?: string) {
    if (lastName) {
        return firstName   ' '   lastName;
    } else {
        return firstName;
    }
}
let tomcat = buildName('dada', 'Cat');
let tom = buildName('dada');

参数默认值

代码语言:javascript复制
function buildName(firstName:string,lastName:string='Cat'){
    return firstName   ' '   lastName;
}
let tomcat = buildName('dada', 'Cat');
let tom = buildName('dada');

剩余参数

代码语言:javascript复制
// 可以使用 ...rest 的方式获取函数中的剩余参数

function push(array,...items){
     items.forEach(function(item){
        array.push(item)
  })  
}

let a = [];
push(a,1,2,3)


function push(array:any[],...items:any[]){
     items.forEach(function(item){
         array.push(item);
    })  
}

let a = []
push(a,1,2,3)

重载

重载允许一个函数接受不同数量或类型的参数时,作出不同的处理

代码语言:javascript复制
function reverse(x: number | string): number | string {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

使用重载定义多个 reverse 的函数类型:

代码语言:javascript复制
function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
    if (typeof x === 'number') {
        return Number(x.toString().split('').reverse().join(''));
    } else if (typeof x === 'string') {
        return x.split('').reverse().join('');
    }
}

静态类型

代码语言:javascript复制
let count : number = 1;

interface dada {
 uname: string,
 age: number
}

const jeskson :dada = {
 uname: 'jeskson',
 age: 12
}

对象类型:

代码语言:javascript复制
const gege: {
 name: string,
 age: number
} = {
 name: 'jeskson',
 age: 12
}
代码语言:javascript复制
const person : string [] = ['dada', 'jeskson', '掘金魔王哪吒']
代码语言:javascript复制
class Person{}
const dada : Person = new Person()

const dada :()=>string = ()=>{return 'jeskson'}

静态类型:对象类型,数组类型,类类型,函数类型

类型注解与类型推断

局部变量:

代码语言:javascript复制
let count : number;
count=12;

如果ts能够自动分析判断变量类型,就不需要,否则就需要使用类型注解。

函数参数和函数的返回类型的注解

代码语言:javascript复制
function getNum(a : number, two : number) : number {
 return a   b
}
const total = getNum(1,2)

never

代码语言:javascript复制
function errorFunction() : never {
 throw new Error()
 console.log('hello world')
}

function forNever() : never {
 while(true) {}
 console.log('hello world')
}

function add({one,two} : {one : number,two : number}) {
 return one   two
}
const total = add({one:1,two:2})

数组类型注解

代码语言:javascript复制
const numberArr : number[] = [1,2,3]

const stringArr : string[] = ['a','b','c']

const undefinedArr : undefined[] = [undefined, undefined]

const arr : (number | string)[] = [1,'string',2]

const dada : {name:string,age:number}[] = [
 {name:'jeskson',age:12},
 {name:'魔王哪吒',age:12},
]

// 类别别名
// type alias
type typeMy = {name:string,age:number}

const dada : typeMy[] = [{name:'jeskson',age:12}]

元组

加强版:

代码语言:javascript复制
const dada : (string | number)[] = ['魔王哪吒','jeskson',12]

// 不常用-元组
const dada1 : [string,string,number] = ["jeskson",12,"dadaqianduan"]

接口

代码语言:javascript复制
interface dada {
 name: 'jeskson';
 age: 12;
 work ?: string;
 say():string;
}

class obj implements dada {
 name="dada"
 age=12
 work="it"
 say(){
  return "dadaqianduan"
 }
}

const selected = (person: dada)=>{
}

// obj.name && console.log(obj.name)

代码语言:javascript复制
class Da {
 content = "掘金魔王哪吒"
 sayHello() {
  return this.content
 }
}

consot da = new Da()
console.log(da.sayHello())
代码语言:javascript复制
class Person {
 name: string;
}
const person = new Person()
person.name = "jeskson"
console.log(person.name)

类的构造函数

代码语言:javascript复制
class Person {
 public name : string;
 constructor(name:string){
  this.name = name
 }
}

// 优化
class Person {
 constructor(public name:string){}
}
class Teacher extends Person{
 constructor(public age:number){
  super('jeskson')
 }
}

const person = new Person('jeskson')

const dada = new Teacher(12)
console.log(dada.age)
console.log(person.name)

Getter,Setter,static

代码语言:javascript复制
class Da {
 constructor(private _age:number){}
 get age() {
  return this._age
 }
 set age(age:number) {
  this._age = age
 }
}

const dada = new Da(12)
代码语言:javascript复制
class Da{
 static sayHello() {
  return "魔王哪吒"
 }
}
console.log(Da.sayHello())

只读属性:

代码语言:javascript复制
class Person{
 public readonly _name:string
 constructor(name:string) {
  this._name = name
 }
}
const person = new Person('jeskson');
console.log(person.name);

抽象类,使用继承抽象类:

代码语言:javascript复制
abstract class Da {
 abstract say()
}
class da extends Da {
 say() {
  console.log('jeskson')
 }
}

tsc -init生成tsconfig.json文件:

compilerOptions配置项

代码语言:javascript复制
"files": []

removeComments 为 true,去掉注释
strict为true,书写规范

// 允许你的注解类型any不用特意标明
"noImplicitAny": true

// 不允许有null值出现
"strictNullChecks": true

// 入口文件
"rootDir": "./src"
// 编译好的文件
"outDir": "./build"

// Generates corresponding '.map' file
// 信息文件,存储位置信息
"sourceMap": true

// Report errors on unused locals
"noUnusedLocals": true

联合类型和类型保护

代码语言:javascript复制
interface Teacher{
 teacher: boolean;
 say:()=>{}
}
interface Student{
 teacher: boolean;
 say:()=>{}
}

//联合类型,类型保护,类型断言
function da(study: Teacher | Student) {
 if(study.teacher) {
  (study as Teacher).say();
 }else{
  (study as Student).say();
 }
}

泛型

代码语言:javascript复制
function fn<T>(params: Array<T>){
 return params;
}
fn<string>(["12","123"]);

使用:

代码语言:javascript复制
class Select {
 constructor(private da: string[]) {}
 getDa(index:number):string{
  return this.da[index];
 }
}
const dada = new Select(["1","2","3"]);
onsole.log(dada.getDa(1));
代码语言:javascript复制
class Select<T> {
 constructor(private da: T[]){}
 getDa(index: number): T{
  return this.da[index];
 }
}
代码语言:javascript复制
interface Girl {
 name: string;
}
class SelectGirl<T extends Girl> {
 constructor(private girls: T[]) {}
 getGirl(index: number): string {
  return this.girls[index].name;
 }
}

class SelectGirl<T extends number | string> {
 constructor(private girls: T[]) {}
 getGirl(index: number): T {
  return this.girls[index];
 }
}

NameSpace

npm init -y生成package.json文件

tsc -init生成tsconfig.json文件

安装VsCode编辑器:

image.png

代码语言:javascript复制
interface Person {
 name: string
}
const teacher: Person = {
 name: 'jeskson'
}

基础类型和对象类型

代码语言:javascript复制
// 基础类型 null, undefined, symbol, boolean, void
const count:number = 12;
const name:string = '掘金魔王哪吒';

// 对象类型
const teacher: {
 name: string;
 age: number;
} = {
 name: 'jeskson',
 age: 12
};

const nums:number[] = [1,2,3]

const goTotal: ()=>number = () => {
 return 123;
}

类型注解和类型推断

代码语言:javascript复制
// type annotation 类型注解

let count:number;
count=123;

// type inference 类型推断,TS会自动的尝试分析变量的类型
代码语言:javascript复制
// 推动不出来,就自己加
function getTotal(firstNumber:number, secondNumber:number) {
 return firstNumber   secondNumber;
}
const total = getTotal(1,2);

函数相关类型

代码语言:javascript复制
// 实战
function getTotal(firstNumber:number, secondNumber:number):number {
 return firstNumber   secondNumber;
}
const total = getTotal(1,2);

// void这个函数不应该有返回值
function sayHello(): void {
 console.log('hello');
}

// never 表示这个函数永远不能执行完成
function errorEmitter(): never {
 while(true){} // 或抛出异常
}
代码语言:javascript复制
function add({first,second}:{first:number;second:number}):number{
 return first second;
}
function getNumber({first}:{first:number}){
 return first;
}

小结:

代码语言:javascript复制
// 基础类型 boolean,number,string,void,undefined,symbol,null

let count: number;
count = 12;

// 对象类型 {},Class,function,[]
const fun = (str:string) => {
 return parseInt(str,10);
}
const fun1: (str:string)=>number = (str) => {
 return parseInt(str,10);
}

const date = new Date();

数组和元组

代码语言:javascript复制
const arr: (number|string)[] = [1,'2',3];
const stringArr: string[] = ['a','b','c'];
const undefinedArr:undefined[] = [undefined];

const objectArr: {name:string,age:number}[] = [{
 name: '掘金魔王哪吒',
 age: 12
}]

// type alias 类型别名
type User = {name:string;age:number};
const objectArr: User[] = [{
 name: '掘金魔王哪吒',
 age: 12
}]

class Teacher {
 name: string;
 age: number;
}
const objectArr: Teacher[] = [
 new Teacher();
 {
  name: 'jeskson',
  age: 12
 }
];

元组

代码语言:javascript复制
const teacherInfo: [string, string, number] = ['dadaqianduan','1024bibi.com',12];

Interface接口

代码语言:javascript复制
interface Person {
 // readonly name: string;
 name: string;
 age?: number;
}
const getPersonName = (person: Person): void => {
 console.log(person.name);
};
const setPersonName = (person: Person, name: string): void=>{
 persono.name = name;
};
const person = {
 name: '掘金魔王哪吒',
 age: 12
};
getPersonName(person);

类的定义与继承

代码语言:javascript复制
class Person {
 name='掘金魔王哪吒';
 getName() {
  return this.name;
 }
}
class Teacher textends Person {
 getTeacherName() {
  return 'teacher';
 }
 getName() {
  return '1024bibi.com'   super.getName()
 }
}

const teacher = new Teacher();
// 重写,字类可以重写父类的东西

类中的访问类型和构造器

代码语言:javascript复制
// private protected public 
class Person {
 public name: string;
 sayHi() {
  console.log('1024bibi.com')
 }
}
const person = new Person();
person.name = '掘金魔王哪吒'
console.log(person.name);

// public 允许我在类的内外被调用
// private 允许在类内被使用
// protected 允许在类内以及继承的子类中是使用
  • constructor
代码语言:javascript复制
class Person {
 public name: string;
 constructor(name: string) {
  this.name = name;
 }
}

const person = new Person('dadaqianduan');
console.log(person.name);
代码语言:javascript复制
// 简化写法
class Person {
 constructor(public name: string) {}
}
代码语言:javascript复制
class Teacher extends Person {
 constructor(public age:number) {
  super('dadaqianduan');
 }
}

// 如果父类没有构造器,也使用空的 super()

静态属性,Setter和Getter

代码语言:javascript复制
class Person {
 constructor(private name: string) {}
 get getName() {
  return this.name;
 }
}

const person = new Person('dadaqianduan');
console.log(person.getName);
代码语言:javascript复制
class Person {
 constructor(private _name: string) {}
 get name() {
  return this._name;
 }
 set name(name: string) {
  this._name = name;
 }
}

设计模式:单例模式,一个类只允许通过这个类,获取一个单例实例

代码语言:javascript复制
class Demo {
 private static instance: Demo;
 private constructor(public name:string) {}
 
 static getInstance(name: string) {
  if(!this.instance) {
   this.instance = new Demo('1024bibi.com');
  }
  return this.instance;
 }
}

//const demo1 = new Demo();
//const demo2 = new Demo();

const demo1 = Demo.getInstance();

抽象类

抽象类只能被继承,不能被实例化

代码语言:javascript复制
abstract class Da {
 width: number;
 getType() {
  return 'dadaqianduan';
 }
 abstract getAra(): number;
}
代码语言:javascript复制
npm init -y

生成package.json文件:

代码语言:javascript复制
{
 "name": "TypeScript",
 "version": "1.0.0",
 "description": "",
 "main": "index.js",
 "scripts": {
  "test: "echo "Error: no test specified" && exit 1"
 },
 "keywords": [],
 "author": "",
 "license": "ISC"
}
代码语言:javascript复制
tsc --init
// Successfully created a tsconfig.json file

// npm uninstall ts-node -g
代码语言:javascript复制
npm install -D ts-node
代码语言:javascript复制
npm install typescript -D

TypeScript中的配置文件

代码语言:javascript复制
// 编译配置文件
// tsconfig.json
要编译的文件
"include" ["./demo.ts"],

联合类型和类型保护

代码语言:javascript复制
interface Bird {
 fly: boolean;
 sing: ()=>{};
}
interface Dog {
 fly: boolean;
 bark: ()=>{};
}
// 类型断言的方式
function trainAnial(animal: Bird | Dog) {
 if(animal.fly) {
  (animal as Bird).sing();
 } else {
  (animal as Dog).bark();
 }
}

// in 语法来做类型保护
function trainAnialSecond(animal: Bird | Dog) {
 if('sing' in animal) {
  animal.sing();
 } else {
  animal.bark();
 }
}
代码语言:javascript复制
// typeof 语法来做类型保护
function add(first: string | number, second: string | number) {
 if(typeof first === 'string' || typeof second === 'string') {
  return `${first}${second}`;
 }
 return first   second;
}

// 使用instanceof语法来做类型保护
class NumberObj {
 count: number;
}

function addSecond(first: object | NumberObj, second: object | NumberObj) {
 if(first instanceof NumberObj && second instanceof NumberObj) {
  return first.count   second.count;
 }
 return 0;
}

Enum枚举类型

代码语言:javascript复制
const Status = {
 OFFLINE: 0,
 ONLINE: 1,
 DELETED: 2
}
function getResult(status) {
 if(status === Status.OFFLINE){
  return 'offline';
 }else if(status === Status.ONLINE) {
  return 'online';
 }else if(status === Status.DELETED) {
  return 'deleted';
 }
 return 'error';
}
代码语言:javascript复制
enum Status {
 OFFLINE,
 ONLINE,
 DELETED2
}
function getResult(status) {
 if(status === Status.OFFLINE){
  return 'offline';
 }else if(status === Status.ONLINE) {
  return 'online';
 }else if(status === Status.DELETED) {
  return 'deleted';
 }
 return 'error';
}

函数泛型

代码语言:javascript复制
// 泛型generic泛指的 类型
function join<T,P>(first: T, second: P) {
 return `${first}${second}`;
}
function anotherJoin<T>(first: T,second: T): T {
 return first;
}

// T[]
function map<T>(params: Array<T>) {
 return params;
}
// join<number,string>(1,'1');
// map<string>(['123']);
join(1,'1');

类中如何使用泛型

代码语言:javascript复制
interface Item {
 name: string;
}
class DataManager<T extends Item> {
 constructor(private data: T[]) {}
 getItem(index: number):string {
  return this.data[index].name;
 }
}

const data = new DataManager({
 {
  name: 'jeskson'
 }
]};

// 用泛型可以声明一些类型:
// 如何使用泛型作为一个具体的类型注解
function hello<T>(params: T) {
 return params;
}
const func: <T>(param: T) => T = hello;

命名空间

代码语言:javascript复制
"use strict"
var Header = (function() {
 function Header() {
  var elem = document.createElement('div');
  elem.innerText = 'This is Header';
  document.body.appendChild(elem);
 }
 return Header;
}());

var Content = (function()=>{
 function Content() {
  var elem = document.createElement('div');
  elem.innerText = 'This is Content';
  document.body.appendChild(elem);
 }
 return Content
}());

使用Parcel打包TS代码

代码语言:javascript复制
yarn add --dev parcel@next

泛型中keyof语法的使用

某一数据类型的key的数组集合,既适用于数组,也适用于对象

代码语言:javascript复制
interface testInter {
    name: string,
    age: number
}
let testArr: string[] = ['dada', 'dada1'];
let testObj: testInter = {name: 'tate', age: 26}

// 数组
function showKey<K extends keyof T, T> (key: K, obj: Array<string>) {
    return key;
}
showKey<number, Array<string>>(1, testArr);

// 对象
function showKey<K extends keyof T, T> (keyItem: K, obj: T): K {
    return keyItem;
}
let val = showKey('name', testObj)

function showKey<K extends keyof T, T> (items: K[], obj: T): T[K][] {
    return items.map(item => obj[item])
}
代码语言:javascript复制
interface Person {
 name: string;
 age: number;
 gender: string;
}
class Teacher {
 constructor(private info: Person) {}
 getInfo(key: string) {
  if(key==='name' || key==='age' || key==='gender') {
   return this.info[key];
  }
 }
}
 
const teacher = new Teacher({
 name: 'jeskson',
 age: 12,
 gender: 'male'
});
const test = teacher.genInfo('name');
代码语言:javascript复制
class Teacher {
 constructor(private info: Person) {}
 // getInfo<T extends keyof Person>(key:string) {
 getInfo<T extends keyof Person>(key: T):Person[T]{
  return this.info[key];
 }
}

装饰器

代码语言:javascript复制
// 类的装饰器
// 装饰器本身是一个函数
// 装饰器通过@符号来使用
代码语言:javascript复制
// 普通方法,target对应的是类的prototype
// 静态方法,target对应的是类的构造函数
function getNameDecorator(target:any,key:string){
 console.log(target,key);
}
class Test {
 name: string;
 constructor(name: string){
  this.name = name;
 }
 @getNameDecorator
 static getName() {
  return '123';
 }
}

接口Interface

有时候我们传入的参数可能会包含很多的属性,但编译器只会检查那些必须的属性是否存在,以及类型是否匹配,而接口就是用来描述这样的结构。

代码语言:javascript复制
function Person(config: {name:string,age:number}) {
 console.log(config.name config.age);
}
console.log(Person({name:'魔王哪吒',age:12}));
// 重构
interface Config {
 name: string;
 age: number;
}
function Person(config: Config) {
 console.log(config.name config.age);
}
// 接口类型检查会检测属性有没有在Config接口中而进行限制

可选属性

接口中的属性有时候是不必须的,有的用得到,有的用不到的情况下,是可选属性,这样对可能存在的属性进行预先定义。

代码语言:javascript复制
interface Config {
 name: string;
 age?: number;
 // [propName: string]: any 转字符串索引签名
}
// [propName: string]: any
// 这个索引签名是为了你能够预见某个对象可能有某些特殊的用途而准备的
// 属性名写错,可以通过索引签名的方式进行屏蔽错误

只读属性

对于一些对象属性只能在对象刚刚创建的时候修改其值,在属性前用readonly来指定只读属性:

代码语言:javascript复制
interface Point {
  readonly x: number;
  readonly y: number;
}
let p:Point = { x: 12, y: 14 }
p.x = 15 // 错误

函数类型

接口能够描述JavaScript中对象拥有的各种各样的外形

函数类型接口:

代码语言:javascript复制
interface Fun {
 (source: string, subString: string): Boolean
}

接口继承

接口是可以相互继承的,能够从一个接口里复制成员到另一个接口里。

代码语言:javascript复制
interface Animal {
 name: string;
 say(): void;
}
interface Person extends Animal {
 work(): void;
 closer: string;
}
class Pro implements Person {
 closer: string;
 name: string;
 say(): void {
 
 }
 work(): void {
 
 }
 constructor(name:string, closer:string) {
  this.name = name;
  this.closer = closer;
 }
}
let g:Person = new Pro("jeskson","it");
g.say();
g.work();
  • 对象类型接口
  • 函数类型接口

接口的定义方式:使用interface关键字

接口中可定义:

  • 确定属性
  • 可选属性
  • 任意属性
  • 只读属性
  1. 确定属性
代码语言:javascript复制
interface UserInfo {
 name: string;
 age: number;
}

const myInfo: UserInfo = {
 name: '魔王哪吒',
 age: 12
}

接口中约束好的确定属性,定义对象变量的时候,不能少,也不能多?‍

  1. 可选属性
代码语言:javascript复制
interface UserInfo {
 name: string;
 age: number;
 sex?: string;
}

const myInfo: UserInfo = {
 name: '魔王哪吒',
 age: 12
}

接口中的可选属性,是表示在对象变量中可以不存在

  1. 任意属性
代码语言:javascript复制
interface UserInfo {
 name: string;
 age: number;
 sex?: string;
 [proName: string]: any;
}

const myInfo: UserInfo = {
  name: "dadaqianduan",
  age: 12,
  test1: '123',
  test2: 'abc',
  test3: 123
};

一旦定义了任意属性,那么确定属性和可选属性的类型都必须是任意属性类型的子类,定义了任意属性后,对象变量中的属性个数才可以出现比接口的属性数量多的情况。

  1. 只读属性
代码语言:javascript复制
interface UserInfo {
  readonly id: number;
  name: string;
  age: number;
  sex?: string;
  [propName: string]: any;
}
代码语言:javascript复制
const myInfo: UserInfo = {
  id: 1,
  name: "dada",
  age: 12,
  test1: "123",
  test2: "abc",
  test3: 123
};

只读属性,也是确定属性,在对象变量定义的时候必须有值,后面不能修改

  • 对象接口,以查询商品列表接口API示例:
代码语言:javascript复制
interface ResponseData {
    resCode: number;
    resData: ResultData[];
    message: string;
}

interface ResultData {
    productId: number;
    productName: string;
}

let resultData = {
    resCode: 0,
    resData: [
        { productId: 1, productName:"TypeScipt实战" },
        { productId: 2, productName:"TypeScipt从入门到精通" },
    ],
    message: "success"
}

function render(res: ResponseData) {
    console.log(res.resCode, res.message)
    res.resData.forEach((obj) => {
        console.log(obj.productId, obj.productName)
    })
}

render(resultData);

只要传入的对象满足接口的必要条件就可以被允许,即使传入多余的字段也可以通过类型检查

  • 绕过检查的方法有3种:
  1. 将对象字面量赋值给一个变量
代码语言:javascript复制
let result = {
    resCode: 0,
    resData: [
        { productId: 1, productName:"TypeScipt实战", remark: "备注"},
        { productId: 2, productName:"TypeScipt从入门到精通" },
    ],
    message: "success"
}
render(result)
  1. 使用类型断言

使用类型断言方式,明确告诉编译器类型是什么,编译器就会绕过类型检查

代码语言:javascript复制
render({
    resCode: 0,
    resData: [
        { productId: 1, productName:"TypeScipt实战", remark:""},
        { productId: 2, productName:"TypeScipt从入门到精通" },
    ],
    message: "success"
} as ResponseData)

render(<ResponseData>{
    resCode: 0,
    resData: [
        { productId: 1, productName:"TypeScipt实战", remark: "备注"},
        { productId: 2, productName:"TypeScipt从入门到精通" },
    ],
    message: "success"
})
  1. 使用字符串索引签名
代码语言:javascript复制
interface ResultData {
    productId: number;
    productName: string;
    [remark: string]: any;  // 字符串索引签名
}

函数接口

  • 函数定义方式:
  1. 在TS中,使用一个变量直接定义函数
代码语言:javascript复制
let add: (x: number, y: number) => number
= (x, y){
  return x y;
};
add(1,2)
  1. 使用接口定义函数
代码语言:javascript复制
interface Add {
    (x: number, y: number): number
}
let myFunc: Add = function(x, y){
  return x y;
};
myFunc(1,2);
  1. 使用类型别名来定义函数

类型别名使用type关键字

代码语言:javascript复制
type Add = (x: number, y: number) => number

可索引类型的接口

代码语言:javascript复制
// 数字索引接口
interface numberIndex {
    [x: number]: string
}
// 相当于声明了一个字符串类型的数组
let chars: numberIndex = ['A', 'B']
代码语言:javascript复制
// 声明一个字符串索引类型的接口
interface stringIndex {
    [x: string]: string
}
代码语言:javascript复制
// 两种索引签名混用
interface stringIndex {
    [x: string]: string
    [z: number]: number    // // Numeric index type 'number' is not assignable to string index type 'string'.
}

interface stringIndex {
    [x: string]: any
    [z: number]: number // Numeric index type 'number' is not assignable to string index type 'string'.
}

上手TypeScipt

对于npm的用户

代码语言:javascript复制
npm install -g typescript

构建第一个TypeScript文件,dada.ts 文件:

代码语言:javascript复制
function dada(person) {
 return "hello"   person;
}
let user = "jeskson";
document.body.innerHTML = dada(uer);

编译代码

在命令行上,运行TypeScript编译器:

代码语言:javascript复制
tsc dada.ts

添加类型注解: string

代码语言:javascript复制
function dada(person: string) {
 return "jeskson" person;
}
let user = "jeskson";
document.body.innerHTML = dada(user);

类型注解

TypeScript里的类型注解是一种轻量级的为函数或变量添加约束的方式。

接口

允许我们在实现接口的时候只要保证包含了接口要求的结构就可以

代码语言:javascript复制
// implements语句
interface Person {
 firstName: string;
 lastName: string;
}

function func(peson: Person) {
 return person.firstName   person.lastName;
}

let user = { firstName: "jeskson", lastName: "User" };

document.body.innerHTML = func(user);

类,支持基于类的面向对象编程

代码语言:javascript复制
class Student {
 fullName: string;
 constructor(public firstName: string, public lastName: string) {
  this.fullName = firstName   lastName;
 }
}

interface Person {
 firstName: string;
 lastName: string;
}

function dada(person: Person) {
 return person.firstName person.lastName;
}

let user = new Student("jeskson","魔王哪吒");
document.body.innerHTML = dada(user);

运行TypeScript Web应用

index.html里输入内容:

代码语言:javascript复制
<!DOCTYPE html>
<html>
    <head><title>TypeScript dada</title></head>
    <body>
        <script src="dada.js"></script>
    </body>
</html>

对象

在JS中,可以任意修改对象属性,TS中不允许

代码语言:javascript复制
// 这是因为,仅声明了对象obj的类型注解是object
let obj: object = {x: 'a', y: 'b'}
obj.x = 3    // Property 'x' does not exist on type 'object'.
代码语言:javascript复制
let obj: {x: string, y: string} = {x: 'a', y: 'b'}
obj.x = 'c'

Symbol

具有唯一的值,可以显式声明,也可直接创建

代码语言:javascript复制
let symbol1: Symbol = Symbol()  // 显示声明
let symbol2 = Symbol()  // 直接创建

// 验证:是否是同一个对象
console.log(symbol1 === symbol2)    // fasle

undefined 和 null

代码语言:javascript复制
// 一旦声明了undefined,就不能再被赋值为任何其他的数据类型了
let udf: undefined = undefined
let nu: null = null

let undf: undefined = 1 
// Type '1' is not assignable to type 'undefined'.

// 默认情况下,undefined和null也不能被赋值给任何其他类型

let num1: number = undefined    
// Type 'undefined' is not assignable to type 'number'.

let num2: number = null 
// Type 'null' is not assignable to type 'number'.
  • 在TS中,undefined和null是任何类型的子类型,所以可以被赋值给其他类型
  • 设置允许被赋值为其他类型

打开tsconfig.js,将strictNullChecks = false(默认true)

void,any,never

  • js中,void操作符可以使任何一个表达式返回undefined
  • void 0 // 将返回undefined
代码语言:javascript复制
// void
let voidFunc = () => {}
  • any:如果不指定TS的变量类型,默认为any类型,可以赋值为任何类型
  • never:永远不会有返回值的类型
代码语言:javascript复制
// 函数抛出异常,永远不会有返回值,类型为never
let error = () => {
    throw new Error('error')
}

// 死循环函数永远没有返回值,类型为never
let endless = () => {
    while(true) {}
}

对数组中的对象按对象的值进行去重

代码语言:javascript复制
let listData = [
  { firstName: "dada", lastName: "abc", size: 18 }
}
代码语言:javascript复制
//js
let obj = {};
listData = listData.reduce((item, next) => {
  if (!obj[next.lastName]) {
    item.push(next);
    obj[next.lastName] = true;
  }
  return item;
}, []);
代码语言:javascript复制
//ts
const obj: {[key: string]: boolean;} = {};
listData = listData.reduce<ListDataItem[]>((item, next) => {
  if (!obj[next.lastName]) {
    item.push(next);
    obj[next.lastName] = true;
  }
  return item;
},[]);

在微信小程序开发中使用Typescript

image.png

image.png

image.png

image.png

模块的概念

“内部模块”现在称为“命令空间”,“外部模块”现在简称为“模块”,模块字其自身的作用域里执行,而不是在全局作用域里。

这意味着定义在一个模块里的变量,函数,类等等在模块外部是不可见的,除非你明确地使用export形式之一导出它们。

相反,如果想使用其它模块导出的变量,函数,类,接口等的时候,你必须要导入它们,可以使用 import 形式之一。

模块的概念:

我们可以把一些公共的功能单独抽离成一个文件作为一个模块,模块里面的变量,函数,类等默认是私有的,如果我们要在外部访问模块里面的数据,我们需要通过export暴露模块里面的数据。暴露后使用import引入模块就可以使用模块里面暴露的数据。

命名空间

命名空间和模块的区别

  • 命名空间:内部模块,主要用于组织代码,避免命名冲突
  • 模块:ts的外部模块的简称
代码语言:javascript复制
namespace A {
interface Animal {
 name: string;
 eat(): void;
}
class Dog implements Animal {
 name: string;
 constructor(theName: string) {
  this.name = theName;
 }
 eat() {
  console.log('dog');
 }
}
class Cat implements Animal {
 name: string;
 constructor(theName: string) {
  this.name = theName;
 }
 eat() {
  console.log('cat');
 }
}
let dog = new Dog('dogdog');
dog.eat();
}
代码语言:javascript复制
import {A,B} from './modules/animal';

var dog = new A.Dog('hei');
dog.eat();

装饰器

装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或参数上,可以修改类的行为。

通俗的讲装饰器就是一个方法,可以注入到类,方法,属性参数上扩展类,属性,方法,参数的功能。

常见的装饰器有:类装饰器,属性装饰器,方法装饰器,参数装饰器

装饰器的写法:

  • 普通装饰器(无法传参)
  • 装饰器工厂(可传参)

方法参数装饰器:

参数装饰器表达式会在运行时当作函数被调用,可以使用参数装饰器为类的原型增加一些元素数据,传入下列3个参数:

  • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
  • 方法的名字
  • 参数在函数参数列表中的索引
代码语言:javascript复制
function logParams(params:any){
 return function(target:any,methodName:any,paramsIndex:any){
  console.log(params);
  console.log(target);
  console.log(methodName);
  console.log(paramsIndex);
 }
}
class HttpClient{
 public url:any|undefined;
 constructor(){}
 getDate(@logParams('xxx') uuid:any){
  console.log(uuid);
 }
}

keyof

代码语言:javascript复制
keyof与Object.keys相似,keyof取interface的键
interface Point {
 x: number;
 y: number;
}
// type keys = "x" | "y"
type keys = keyof Point;
代码语言:javascript复制
// 无法确认返回类型
// 无法对 key 做约束
const data = {
 a: 1,
 b: 2
}

function get(o: object, name: string) {
 return o[name]
}

使用keyof:

代码语言:javascript复制
function get<T extends object, K extends keyof T>(o: T, name: K): T[K] {
  return o[name]
}

?: 运算符

代码语言:javascript复制
T extends U ? X : Y

type isTrue<T> = T extends true ? true : false

tsconfig.json

tsconfig.json文件中指定了用来编译这个项目的根文件和编译选项

tsconfig.json示例文件:

代码语言:javascript复制
//"compilerOptions"可以被忽略,这时编译器会使用默认值。
//使用"files"属性
//"files"指定一个包含相对或绝对文件路径的列表。
{
    "compilerOptions": {
        "module": "commonjs",
        "noImplicitAny": true,
        "removeComments": true,
        "preserveConstEnums": true,
        "sourceMap": true
    },
    "files": [
        "core.ts",
        "sys.ts",
        "types.ts",
        "scanner.ts",
        "parser.ts",
        "utilities.ts",
        "binder.ts",
        "checker.ts",
        "emitter.ts",
        "program.ts",
        "commandLineParser.ts",
        "tsc.ts",
        "diagnosticInformationMap.generated.ts"
    ]
}
//使用"include"和"exclude"属性
//如果"files"和"include"都没有被指定,编译器默认包含当前目录和子目录下所有的TypeScript文件
//排除在"exclude"里指定的文件
{
    "compilerOptions": {
        "module": "system",
        "noImplicitAny": true,
        "removeComments": true,
        "preserveConstEnums": true,
        "outFile": "../../built/local/tsc.js",
        "sourceMap": true
    },
    "include": [
        "src/**/*"
    ],
    "exclude": [
        "node_modules",
        "**/*.spec.ts"
    ]
}

查看模式: http://json.schemastore.org/tsconfig.

代码语言:javascript复制

0 人点赞