目录
TypeScript 其实就是 JavaScript 的超集,也就是说 TypeScript 是建立在 JavaScript 之上的,最后都会转变成 JavaScript。TypeScript我也是一个初学者,在这里,我会简单总结一些关于TypeScript的特性,具体细节感兴趣者可参考中文官方文档。
基础静态类型
TypeScript最大的一个特点就是变量是强类型的,也就是说,在声明变量的时候,我们必须给他一个类型。常用的基础静态类型类型有:string、null、undefined 、Array、 boolean、 any 、void、 Tuple 、enum等
- const test1:string = "s"//字符串
- const test2:number = 1//数字
- const test3:null = null//null
- const test4:Array<number> =[1,2]//数组
- const test5:boolean = false//布尔
- const test6:any = 10//任意类型
- const test7:undefined = undefined//undefined
对象类型
对象类型大概可以分为四种
- //对象类型--我们可以直接使用{propertyName:type,...}的形式来约束类型的名称和类型
- const ts:{name:string,age:number} = {name:"hello",age:22}
-
- //数组类型--基础静态类型的数组也可以为对象类型,这里就用string类型示例,其他类型数组都差不多
- const strArr:string[] =['a','b']
-
- //数组类型也可以这样表示
- const strArr:Array<string> = ['1','2']
-
- //类类型--需要自己先创建一个类,然后声明属性时约束其为创建的类
- class Class1{
- name:string;
- age:number
- }
- const class1:Class1 = {name:"a",age:12}
- const class2:Class1 = new Class1()
-
- //函数类型--声明变量为函数和返回值的类型
- const func:()=>string = ()=>"hello TypeScript"
- const man: { name: string, age: number }[] = [
- { name: "小A", age: 22 },
- { name: "小B", age: 22 },
- ]
这种形式看起来比较麻烦,而且如果有同样类型的数组,写代码也比较麻烦,TypeScript 为我们准备了一个概念,叫做类型别名(type alias)。定义别名的时候要以type关键字开始。
- //type alias 类型别名
- type man = { name: string, age: number };
-
- //然后再定义数组的时候我们就可以用别名了
- const manArr: man[] = [
- { name: "小A", age: 22 },
- { name: "小B", age: 22 },
- ]
还有我们如何控制一个数组中既有数字或者有字符串呢, 很简单,只要加个(),然后在里边加上|就可以了,具体如代码所示。
const arr3: (number | string)[] = [1, "2", 3];
类型注解即我们声明变量时指明了变量的类型,这就变量注解。
let count1:number;
TypeScript里,在有些没有明确指出类型的地方,类型推论会帮助提供类型。
const x = 2;
变量x的类型被推断为数字。这种推断发生在初始化变量和成员,设置默认参数值和决定函数返回值时。
元组和数组类似,但是类型注解时会不一样,元组是对数组中的每一个元素都确定了类型。其实你可以把元组看成数组的一个加强,它可以更好的控制或者说规范里边的类型。
- //元组
- const xiaoge: [string, string, number] = ['a', 'b', 28];
-
- //元组数组
- const xiaoge: [string, string, number][] = [['a', 'b', 28],['a1', 'b1', 28],['a2', 'b2', 28]]
接口声明示例:如下代码所示,我们可以在接口中指定属性的类型,属性名?代表当前属性为可选字段(可以赋值,也可以不赋值)
[propname:string]:any 用于新增一些任意属性,属性的名字是字符串类型,属性的值可以是任何类型。
- interface Person {
- name: string;
- age: number;
- height?: number;
- [propname:string]:any;//any为任意类型
- say():string//可声明函数
- }
接口和接口之间可以继承,使用关键字extends,子接口将拥有父级接口的所有属性和函数
- interface Student extends Person{
- studentNo:string
- }
-
- //使用接口进行注解,被注解的变量需要对接口中所有不是可选属性的属性进行赋值,不然代码就会提示错误
- const stu:Student = {name:"小A",age:20,studentNo:"A01",say() {
- return "我是小A"
- },}
使用类实现接口,实现需要用到关键字implements,也需要对接口中所有不是可选属性的属性进行赋值,函数也必须实现,不然代码就会提示错误
- class StuB implements Student{
- name = "小B"
- age = 22
- studentNo = "B01"
- say(){return "hello"}
- }
TypeScript类主要内容有:
类的基本使用
就像这样,可以声明一些变量和方法,使用类时可以通过new关键字生成对象
- class Animal{
- content = "动物";
- say(){
- return this.content
- }
- }
-
- const animal:Animal = new Animal()
类的继承、重写和super关键字
继承:使用extends关键字,子类将拥有父类的所有属性和方法,当然也可以自己的属性和方法
- class Bird extends Animal{
- fly(){
- return "I can fly"
- }
- }
-
- const bird:Bird = new Bird();
- console.log(bird.say())//动物
- console.log(bird.fly())//I can fly
重写:类的重写主要是子类对父类函数的重写,就是父类有一个函数,子类定义一个与父类同名同参的函数,然后这个函数可以与父类有不一样的实现。
- //Animal类也是有say()函数的,这里子类再次定义say()函数就是对父类函数的重写
- class Bird extends Animal{
- say(){
- return "I am a bird"
- };
- fly(){
- return "I can fly"
- }
- }
super关键字:用于子类调用父类的属性和方法
- class Bird extends Animal{
- say(){
- return super.content+ "-- bird"//调用父类函数就可以用super.say()
- };
- fly(){
- return "I can fly"
- }
- }
类的访问类型
类的访问类型只有三种public、private、protected
- //public
- class Person {
- public name = "person";
- public sayHello() {
- console.log(this.name + " hello");
- }
- }
- const person = new Person()
- console.log(person.name);//person(因为是public,所以外部能访问到Person.name)
- person.sayHello();//person hello
-
- //private,它的子类访问不到name属性
- class Person2 {
- private name = "person";
- public sayHello() {
- console.log(this.name + " hello");
- }
- }
- const person2 = new Person2()
- //console.log(person2.name);编译不通过Property 'name' is private and only accessible within class 'Person2'.
- person2.sayHello();//person hello
-
-
- //protected,它的子类可以访问到name属性
- class Person3 {
- protected name = "person";
- public sayHello() {
- console.log(this.name + " hello");
- }
- }
- const person3:Person3 = new Person3()
- //console.log(person3.name);编译不通过:Property 'name' is protected and only accessible within class 'Person3' and its subclasses.
- person3.sayHello();//person hello
类的构造函数
类构造函数的基本使用,使用constructor函数
-
- class TestA{
- public name:string;
- constructor(name:string){
- this.name = name
- }
- }
-
- //可以简写为
-
- class TestA{
- constructor(public name:string){
- this.name = name
- }
- }
-
- const t1:TestA = new TestA("小A");
- console.log(t1.name);//小A
子类继承父类后构造函数中必须使用super调用父类的构造函数
- //继承的构造函数
- class TestB extends TestA{
- constructor(public age:number){
-
- //在子类的构造函数中必须写super(),若不写会报错
- super('小B')
- this.age = age;
- }
- }
- const testB:TestB = new TestB(23)
- console.log(testB.name);//小B
- console.log(testB.age);//23
类的Getter、Setter和Static
当变量被声明为私有变量时,无法直接访问到属性值,这里就可以通过设置get和set函数来取值赋值,使用时就和获取public变量一样了。
- class GSClass{
- constructor(private _age:number){}
- get age(){
- return this._age
- }
- set age(age:number){
- this._age = age
- }
- }
-
- const gs = new GSClass(23);
- gs.age = 24;
- console.log(gs.age);
static用于不需要实例化对象就可以调用类的方法
- class Boy{
- static sayLove(){
- return "I Love You"
- }
- }
- console.log(Boy.sayLove());
只读属性
使用readonly关键字进行修饰,顾名思义,只读属性只用于数据读取,不能进行赋值
- class Server{
- public readonly _name:string;
- constructor(name:string){
- this._name = name
- }
- }
- const user = new Server("rr")
- console.log(user._name);
抽象类
使用abstract关键字修饰的类为抽象类
抽象类中可以声明抽象函数(也可以有普通函数),也是用abstract关键字修饰
子类继承抽象类必须实现抽象类中所有抽象方法
- //抽象类
- abstract class A{
- abstract skill();
- }
-
- class B extends A{
- skill() {
- console.log("s1");
- }
- }
- interface Waiter {
- anjiao: boolean;
- say: () => {}
- }
- interface Teacher {
- anjiao: boolean;
- skill: () => {}
- }
- //
- function judgeWho(person: Waiter | Teacher) {
- //断言
- if (person.anjiao) {
- (person as Teacher).skill();
-
- } else {
- (person as Waiter).say();
- }
- }
-
- function judegeWhoTwo(person: Waiter | Teacher) {
- if ("skill" in person) {
- person.skill();
- } else {
- person.say();
- }
- }
-
- function add(first: string | number, second: string | number) {
- if (typeof first === "string" || typeof second === "string") {
- return `${first}${second}`
- }
- return first + second
- }
-
-
- class NumberObj{
- count:number;
- }
- //instanceof 只能用在类上
- function addObj(first: object| NumberObj,second:object| NumberObj){
- if(first instanceof NumberObj && second instanceof NumberObj){
- return first.count + second.count
- }
- return 0;
- }
- //默认值从0开始
- enum Status {MESSAGE,SPA,DABAOJIAN}
-
- //这样枚举就从1开始了
- //enum Status {MESSAGE = 1,SPA,DABAOJIAN}
-
- function getServe(status:number){
- if(status === Status.MESSAGE){
- return "message"
- }else if (status === Status.SPA){
- return "spa"
- }else if (status === Status.DABAOJIAN){
- return "dajiao"
- }
- }const result = getServe(Status.MESSAGE);
- // const result = getServe(0);
- console.log(result);
-
- ///这样输出为数字 0 , 1 ,2
- console.log(Status.MESSAGE);//0
- console.log(Status.SPA);//1
- console.log(Status.DABAOJIAN);//2
-
- //反查 (其实数字代表的是具体枚举代表的值)
- console.log(Status[0]);//MESSAGE
- console.log(Status[1]);//SPA
- console.log(Status[2]);//DABAOJIAN
函数上泛型的使用
- function join(first:string|number ,second:string|number){
- return `${first}${second}`
- }
- join("ss","com")
-
- //保证first和second的类型一致
- function join2
(first:T ,second:T){ - return `${first}${second}`
- }
- join("ss","com")
- join2<number>(1,2);
-
- //数组
- function myFunc
(params:Array){ - return params;
- }
- myFunc<string>(["123","456"]);
-
- //多种类型
- function myFunc2
(first:T,second:P){ - return `${first}${second}`
- }
- myFunc2<string,number>("2",1);
类上泛型的使用
- interface TT{
- name:string
- }
-
- class SelectGirl
extends TT>{ - constructor(private girls:T[]){}
-
- getGirl(index:number):string{
- return this.girls[index].name;
- }
- }
- const selectGirl = new SelectGirl([{name:"小A"} ,{name:"小B"},{name:"小C"}]);
- console.log(selectGirl.getGirl(1));