TS语法

338 阅读5分钟

把一些类型错误,就直接扼杀在编译过程当中,不用运行就已经知道有错

tsc ./xxx.ts ==> node ./xxx.js 运行TS文件

类:实例的属性,必须加上类型

  • 在构造器当中的入参,配置实例属性访问修饰符 public/private/protected
  • 继承语法:除了类型注解(type annotation)外与JS一模一样 -public作用:;
  • 默认访问权限为public,name:string
  • 定义name为实例属性(实例属性可以不用单独声明)
  • 规定name在Animal内外作用域均可访问,pravite则只能在Animal作用域内访问
  • 默认的xxx属性与当前实例绑定,可以不用写this.xxx = xxx
  • pravite也可以默认的xxx属性与当前实例绑定,可以不用写this.xxx = xxx,只不过pravite则只能在Animal作用域内访问
  • protected:实例属性只能在Animal作用域及其子类的作用域访问实例属性xxx
  • 凡是拿不准实例属性的访问权限的情况下,就直接public完事
class Animal {
   // 默认访问权限为public
   // name: string;
   constructor(public name: string) {
      // this.name = name;
   }

   move(distanceInMeters: number = 0) {
      console.log(this.name);
      console.log(`${this.name} moved ${distanceInMeters}m.`);
   }
}

/* 继承的语法,除了类型注解(type annotation)外与JS一模一样 */
class Snake extends Animal {
   constructor(name: string) {
      super(name);
   }
   
   move(distanceInMeters = 5) {
      console.log("Slithering...");

      // 属性“name”为私有属性,只能在类“Animal”中访问。ts(2341)
      console.log(this.name);
      super.move(distanceInMeters);
   }
}

let sam = new Snake("Sammy the Python");

// 属性“name”为私有属性,只能在类“Animal”中访问。ts(2341)
console.log(sam.name);

sam.move();

泛型

  • 在类上使用泛型
//3.类中使用了泛型,类也需要声明泛型
class Greeter<T> {
    //2.参数也得声明为T
    greeting: T;
    //1.想让message入参支持任意类型
    constructor(message: T) {
        this.greeting = message;
    }
    greet() {
        return this.greeting;
    }
}
//4.将泛型T具体化
let greeter = new Greeter<string>("Hello, world");

let button = document.createElement('button');
button.textContent = "Say Hello";
button.onclick = function() {
    alert(greeter.greet());
}

document.body.appendChild(button);

//泛型最最常用场景
//数组里面的每一元素,必须是字符串
let names:string[] = [] //写法一
let names:Array<string> = []  //写法二

联合类型及类型守卫

//name的类型可以是A或B或C 联合类型
//声明一个类型别名 (给联合类型 string | string[] 起一个NameOrNameArray类型别名)
type NameOrNameArray = string | string[];

function createName(name: NameOrNameArray) {
    if (typeof name === "string") {
        return name;
    }
    else {
        return name.join(" ");
    }
}

var greetingMessage = `Greetings, ${ createName(["Sam", "Smith"]) }`;
alert(greetingMessage);

let frends:string | string[]

type NameOrArray = string | string[]
let args:NameOrArray = []

接口interface

接口是对具有特定key-value对象的声明

interface Light {
    //灯光强度
    strength: number;
    //灯光颜色
    color: string;
    //代表可选属性,可给可不给,不会报错
    name?:string
}

let light:Light

//会报错,显示缺少strength + color 属性
 light = {}
 
 //报错,多了position属性
 light = {
     strength:100,
     color:"#fff",
     position:["50px","80px"]
 }
 
 //或多或少都会报错
  • 数组里面嵌套对象时,需单独给对象造一个接口
  • xxx?:string 代表可选属性,可给可不给
interface Actor {
   name: string;
   role: string;
   avatarAddress: string;
}

interface Film {
   filmId: number;
   name: string;
   poster: string;
   actors: Array<Actor>;

   // 可选属性
   photos?: string[];
}

function deformatFilm(film: Film) {
   console.log("deformatFilm", film);
}

deformatFilm({
   filmId: 1234,
   name: "万里归途",
   poster: "https",
   actors: [
      {
         name: "饶晓志",
         role: "导演",
         avatarAddress: "https://pic.maizuo.com/usr/movie/3c1b606e514b6cd66d376b56275dcc76.jpg",
      },
      {
         name: "张译",
         role: "演员",
         avatarAddress: "https://pic.maizuo.com/usr/movie/ff9aafa8c6033a1277d5ecd65822f8ae.jpg",
      },
   ],
   // photos: ["url1", "url2"],
});

函数

  • 有入参,有返回值,不满足条件(入参+返回值要求)报错
  • 有入参,无返回值,我们有具体返回值会给void重新赋值,不会报错
  • 有入参,入参类型错,报错
  • 有入参,可设置可选Fn(food?:number)=>void
  • 有入参,我不接收,不会报错;一旦接收,就必须按照顺序+类型正确即可
  • 还可以给函数声明一个类型别名

  • 类是有具体声明,类是new出来的,我们想要类得到的实例,实现implements某个接口规范,我们可以使用类来实现接口,
  • 接口是没有实际功能的,class是具有实际功能的
  • 接口是new不了,class是可以new的
  • class还可以新增内容,但必须包含接口所有内容(?)

命名空间namespace

  • 一个命名空间,实现域名隔离,防止不同模块下的(变量,函数,接口,类...)与其他模块形成命名冲突
  • 命名冲突里面可以放任意内容

接口

  • 接口当中使用可索引属性
  • 例如人:人有很多属性,我们预留属性给使用者拓展
  • [key:string]:any
  • 任意多个【字符串:any】类型的key-value
  • 作用:随意拓展任意多个属性

接口继承

  • interface IStudent extends IPerson
  • IStudent接口 继承 IPerson 接口的属性

类可以单继承(一个类),多实现(多个接口)

  • class Student extentds Person implements IWork,IFigher{}

枚举

  • enum
  • 不赋值,枚举就是对应的索引号;有赋值,枚举就是对应的值
  • 不要将枚举的类型声明文件到dts文件当中,编译后会报 cant find module

TS和JS当中Void

  • ts:void代表无返回值
  • is:void代表返回undefined

never:永不返回

  • 除了never,都可以给any赋值
  • 无返回值,死循环,抛出错误

类型断言

  • 告诉编译器,我知道自己在干什么
  • 消除报错
function fn():number | string{
    // Math.random()取值范围: [0,1)
    return Math.random()>0 ? "string" : 123
}

//断言fn()的返回值为string
(<string>fn()).length  //方法一
(fn() as string).length //方法二

编译选项

- noImplicitAny:true //不允许有隐式的any
- strictNullChecks:true //不允许将null和undefined赋值给任何其他类型(any除外)
- strictPropertyInitialization:true //(前提:strictNullChecks:true)类实例属性必须初始化,给它赋值 this.name = name
- noImplicitThis:true //不允许this隐式的为any类型
- noImplicitRetures:true //强制函数的所有分支都有明确的返回
- strict:true //启用所有的严格选项(激活了noImplicitAny,strictNullChecks,strictPropertyInitialization,noImplicitThis),想关掉其他的选项,在后面覆盖即可

声明类型并导出外界使用

  • export declare 表示导出类型
  • import type 表示导入类型
    //导出
    export declare enum Major {
        HTML="HTML5",
        CSS="CSS"
    }
    
    export declare interface ICodingStudent {
        name:string,
        major:Major
    }
    
    //导入类型 / 值 
    import type {ICodingStudent} from "./env"  //(类型+type)
    import  {Major} from "./env"