前言
vue3曾经公布了,ts的脚步曾经拦截不住了,还只会es6?别想了,人家都曾经在口头了,以下是ts的根本系列教程,ts的根本语法,高级语法等,以及在vue我的项目中如何利用ts,跟着我连忙撸起来吧。
根本数据类型
数字
const a: number = 3;
字符串
const b: string = "1";
数组
const c: number[] = [1, 2, 3];const d: Array<number> = [1, 3];const arr: any[] = [1, "33", true];
元组
能够为数组中的每个参数定义绝对应的类型
const e: [number, string] = [1, "ww"];
枚举
enum error { blue = 3, "orange",}const f: error = error.orange;console.log(f); //输入4
tips
- 如果
未赋值
的上一个值是数字
那么这个未赋值的值
的是上一个值的值+1- 如果
未赋值
的上一个值未赋值
那么输入的就是它的下标
- 如果
未赋值的上一个值的值是非数字
,那么必须赋值
布尔类型
const g: boolean = true;
对象
const i: object = {};
undefined
罕用于组合类型
let j: number | undefined;
null
let k: null;
void
指定办法类型,示意没有返回值,办法体中不能return
function aa(): void { console.log(1);}//如果办法有返回值,能够加上返回值的类型function bb(): number { return 1;}
never
其余类型 (包含null和undefined)的子类型,代表从不会呈现的值
let l: never;//匿名函数并抛出异样l = (() => { throw new Error("111");})();
任意类型
让参数能够是任何一种类型
let h: any = 1;h = true;h = "st";
函数
函数申明
function cc(): void {}
办法传参
function getUserInfo(name: string, age?: number, school: string = "清华大学") { return `name:${name}--age:${age}--school:${school}`;}
tips: ?代表这个参数可传可不传,不传就是undefined,也可定义个默认的值
残余参数
传递多个时,如果用了残余参数,就能够把未定义的形参转换为数组。
function sum (a: number, b: number, ...arr: number[]): number { let sum: number = a + b; arr.forEach((element) => { sum += element; }); console.log(arr); [3,4,5] return sum;}console.log(sum(1, 2, 3, 4, 5)); //15
函数重载
function reload(name: string): string;function reload(age: number): string;function reload(param: any): any { return typeof param === "string" ? `我是:${param}` : `我的年龄:${param}`;}console.log(reload(18)); //年龄
tips:被重载
的办法,是没有办法体
,能够依据参数的类型走其中一个办法并判断参数,但如果传入的参数类型不是任何被重载办法的参数类型
就不容许通过。
第 1 个重载(共 2 个),“(name: string): string”,呈现以下谬误。 类型“never[]”的参数不能赋给类型“string”的参数。 第 2 个重载(共 2 个),“(age: number): string”,呈现以下谬误。 类型“never[]”的参数不能赋给类型“number”的参数
类
class Person { // 公有变量 private name: string; // 构造函数 constructor(name: string) { this.name = name; } // 获取名字 getName(): string { return this.name; } // 设置名字 setName(name: string): void { this.name = name; }}let p = new Person("张三");p.setName("李四");console.log(p);
继承
class Son extends Person { // 动态属性 public static age: number = 18; // 学校 public school: string; //构造方法 constructor(name: string, school: string) { // 拜访派生类的构造函数中的 "this" 前,必须调用 "super",初始化父类构造函数 --并把参数传给父类 super(name); //把传进来的school赋值给全局变量 this.school = school; } //静态方法 static run(name: string): string { return `${name}在跑步,他的年龄才${this.age}`; }}let son = new Son("王五", "清华大学");son.setName("赵六"); // 公有类也不能在子类的内部拜访,但可通过公开的办法中进行赋值和拜访console.log(son);console.log(Son.run("方七"));console.log(Son.age);
tips:
- public 在以后类外面,子类,类里面都能够拜访
- protected 在以后类和子类外部能够拜访,类内部无法访问
- private 在以后类外部可拜访,子类,类内部都无法访问。
- 属性不加修饰符,默认就是私有的 (public)
多态
通过形象办法/办法重载--实现多态--多态的作用是用来定义规范
// 形象父类abstract class Animal { private name: string; constructor(name: string) { this.name = name; } //形象成员--办法 abstract eat(): any; //形象成员--属性 protected abstract ages: Number; sleep(): void { console.log("睡觉"); }}class cat extends Animal { ages: Number = 2; constructor(name: string) { super(name); } //非抽象类“cat”不会主动实现继承自“Animal”类的形象成员“eat”, 必须手动定义父类中的形象办法--多态 eat(): string { return "猫吃鱼"; } //多态 sleep(): string { return "猫在睡觉"; }}console.log(new cat("33").sleep());
tips:
- 抽象类无奈
实例化
。- 非抽象类继承形象父类时
不会主动实现
来自父类的形象成员,必须手动定义
父类中的形象成员,否则报错。- 形象成员包含
属性
和办法
接口
在面向对象的编程中,接口是一种标准的定义,它定义了行为和动作的标准,
在程序设计外面,接口起到一种限度和标准的作用。
接口定义了某一批类所须要恪守的标准,接口不关怀这些类的外部状态数据,也不关怀这些类里办法的实现细节,它只规定这批类里必须提供某些办法,提供这些办法的类就能够满足理论须要。ts中的接口相似于java,同时还减少了更灵便的接口类型,包含属性、函数、可索引和类等。
属性接口
interface InterfaceName { first: string; second?: string; //加个问号,接口属性就能够变成可传可不传了,不传默认是undefined。}//打印变量function logParam(name: InterfaceName): void { console.log(name.first, name.second, 11);}//定义参数const obj = { first: "1", second: "fff", three: 1 };//logParam({ first: "1", second: "1", three: 1 }); //报错,只能传接口定义的值logParam(obj);
tips: 用个变量来存储传入的变量,这样能够传入定义的接口以外的值,否则如果间接传入对象中无接口定义的值会报错,所以倡议接口定义了哪些值就传哪些值。
函数类型接口
对办法传入的参数类型,以及返回值类型进行束缚,可批量进行束缚。
interface keyMap { (key: string, value: string): string;}let logKeyMap: keyMap = function (key1: string, value: string): string { return key1 + value;};console.log(logKeyMap("key1", "value"));
tips: 接口只对传入的参数的类型和参数的个数进行束缚,不对参数名称进行束缚。
可索引接口
- 束缚数组
interface Arr { [index: number]: string;}let ss: Arr = ["2121"];
- 束缚对象
interface Obj { [index: string]: string;}let interfaceArr: Obj = { aa: "1" };
tips:
- 对
数组
进行束缚,index
后必须跟着number
类型。- 对
对象
进行束缚,index
后必须跟着string
类型- 索引签名参数类型必须为 "string" 或 "number"
类类型接口
- 对
类
进行束缚,相似抽象类
的实现。
interface Animals { name: string; eat(): void;}class Dogs implements Animals { name: string; constructor(name: string) { this.name = name; } eat() {}}
- 接口继承--接口能够继承接口
interface Dog { eat(): void;}interface Persons extends Dog { work(): void;}class Cat { code() { console.log("猫在敲代码"); }}//可继承类后再实现接口class SuperMan extends Cat implements Persons { eat(): void { console.log(1); } work(): void { console.log(2); }}let superMan = new SuperMan();superMan.code();
tips: 类接口会对类的属性
和办法
进行束缚,相似非抽象类继承抽象类时必须实现某些办法和属性,但对属性和办法的类型的束缚更加严格,除了办法void类型
可被从新定义
外,其余属性或办法的类型定义须要和接口保持一致。
泛型
软件工程中,咱们不仅要创立统一的定义良好的api,同时也要思考可重用性。
组件不仅可能反对以后的数据类型,同时也能反对将来的数据类型,这在创立大型零碎时为你提供了非常灵便的性能
泛型就是解决类
、接口
、办法
的复用性
,以及对不特定数据类型
的反对。
要求:传入的参数和返回的参数统一
函数的泛型
function getDate<T>(value: T): T { return value;}console.log(getDate<number>(123));
tips: 这里的T
可改成其余任意值但定义的值,和传入的参数以及返回的参数是一样的,个别默认写法是T,也是业内标准的抉择。
类的泛型
class MinClass<T> { public list: T[] = []; //增加 add(value: T): void { this.list.push(value); } //求最小值 min(): T { //假如这个值最小 let minNum = this.list[0]; for (let i = 0; i < this.list.length; i++) { //比拟并获取最小值 minNum = minNum < this.list[i] ? minNum : this.list[i]; } return minNum; }}//实例化类 并且指定了类的T的类型是numberlet minClass = new MinClass<number>(); minClass.add(23);minClass.add(5);minClass.add(2);console.log(minClass.min()); //实例化类 并且指定了类的T的类型是string,则其办法的传参和返回都是string类型let minClass2 = new MinClass<string>();minClass2.add("23");minClass2.add("5");minClass2.add("2");console.log(minClass2.min());
接口的泛型
- 第一种写法
interface ConfigFn { //标准参数类型,返回值类型 <T>(value: T): T;}let getData: ConfigFn = function <T>(value: T): T { return value;};console.log(getData<string>("z11"));
- 第二种写法
interface ConfigFn<T> { //参数类型 ,返回值类型 (value: T): T;}//接口办法function getData<T>(value: T): T { return value;}//应用接口let myGetDate: ConfigFn<string> = getData;console.log(myGetDate("3"));
tips:接口的泛型只针对函数类型的接口
类当做参数传入泛型类
//用户类--和数据库表字段进行映射class User { username: string | undefined; password: string | undefined; //构造函数-初始化参数 constructor(param: { username: string | undefined; password?: string | undefined; }) { this.username = param.username; this.password = param.password; }}//数据库类class Db<T> { add(user: T): boolean { console.log(user); return true; } updated(user: T, id: number): boolean { console.log(user, id); return true; }}let u = new User({ username: "张三",});//u.username = "李四";u.password = "111111";let db = new Db<User>();db.add(u);db.updated(u, 1);
tips: 类的参数名和类型都做了束缚。
模块
外部模块称为命名空间,内部模块简称为模块,模块在其本身的作用域里执行,而不是在全局作用域里;
这意味着定义在一个模块里的变量、函数、类等等在模块内部是不可见的,除非你明确的应用export
模式之一导出它们。
相同,如果想应用其它模块导出的变量,函数,类,接口等的时候,你必须要导人它们,能够应用import
模式之一。
咱们能够一些公共的性能独自抽离成一个文件作为一个模块。
模块外面的变量、函数、类等默认是公有的,如果咱们要在内部拜访模块外面的数据(变量、函数、类)
咱们须要通过export
裸露模块外面的数据(变量、函数、类...)。
裸露后咱们通过import
引入模块就能够应用模块外面裸露的数据(变量、函数、类...)
//modules/db.tsfunction getDate(): any[] { console.log("获取数据"); return [ { userName: "张三", }, { userName: "李四", }, ];}//一个模块外面能够用屡次// export { getDate };//一个模块外面只能用一次export default getDate;
import { getDate as getDbDate } from "./modules/db"; import getDbDate from "./modules/db"; getDbDate();
tips: 这个调试时浏览器中不能间接应用,可在node
和weakpack
的环境中调试。
命名空间
在代码量较大的状况下,为了防止各种变量命名相冲突,可将类似性能的函数、类、接口等搁置到命名空间内
TypeScript的命名空间能够将代码包裹起来,只对外裸露须要在内部拜访的对象。
命名空间和模块的区别
- 命名空间:外部模块,次要用于组织代码,防止命名抵触。
- 模块:ts内部模块的简称,偏重代码的复用,一个模块里可能会有多个命名空间。
// modules/Animal.tsexport namespace A { interface Animal { name: String; eat(): void; } export class Dog implements Animal { name: String; constructor(theName: string) { this.name = theName; } eat() { console.log("我是" + this.name); } }}export namespace B { interface Animal { name: String; eat(): void; } export class Dog implements Animal { name: String; constructor(theName: string) { this.name = theName; } eat() {} }}
import { A, B } from "./modules/Animal"; let ee = new A.Dog("小贝"); ee.eat();
装璜器
- 类装璜器:类装璜器在类申明之前被申明(紧靠着类申明),类装璜器利用于类构造函数,能够用于监督,批改或者替换类定义。
function logClass(params: any) { console.log(params); //params 就是指代以后类--HttpClient params.prototype.apiUrl = "动静扩大属性"; params.prototype.run = function () { console.log("动静扩大办法"); }; params.prototype.getDate = function () { console.log("动静扩大办法2"); };}@logClassclass HttpClient { constructor() {} getDate() { console.log(1); }}let http: any = new HttpClient();console.log(http.apiUrl);http.run();http.getDate();
tips: 装璜器会笼罩被装璜的类中的办法。
- 装璜器工厂
可传参的装璜器
function logClassB(param: string) { return function (target: any) { console.log(target, "装璜器以下的类"); console.log(param, "装璜器传进来的属性"); };}@logClassB("小慧")class HttpClients { constructor() {} getDate() {}}let https: any = new HttpClients();console.log(https);
- 构造函数装璜器
function logClassC(target: any) { console.log(target, 1111); //用在这里继承指标类并重载办法和属性 return class extends target { a: any = "我是批改后的属性"; getDate() { console.log(this.a + "--装璜器中的办法输入的"); } };}@logClassCclass HttpClient2 { public a: string | undefined; constructor() { this.a = "我是构造函数外面的a"; } getDate() { console.log(this.a); }}const https2 = new HttpClient2();https2.getDate();
未完待续~
下期预报:在vue中应用ts。