ts知识点

安装

npm install typescript -g
yarn global add typescript

执行

tsc Demo1.ts
npm install -g ts-node ts-node Demo1.ts

静态类型

  • : number 就是定义了一个静态类型
  • 如果使用了静态类型,不仅意味着变量的类型不可以改变,还意味着类型的属性和方法也跟着确定了
    const count: number = 1;

基础类型 && 对象类型

  • 基础静态类型,只要在声明变量的后边加一个:号,然后加上对应的类型,
    number string null undefined symbol boolean void
    const count : number = 918;
  • 对象类型可以有几种形式:对象类型、数组类型、类类型、函数类型
    const arr: String[] = ["sds", "sdsd", "sdw"];

const kk: () => string = () => { return "sdsd";};

类型注解 && 类型推断

  • 类型注解如const count:number = 12
  • 如果 ts 能够自动分析变量类型,我们可以不定义;如果 ts 无法分析变量类型,就需要使用类型注解;
  • total 这个变量不需要加类型注解:当 one 和 two 两个变量加上注解后,TypeScript 就可以自动通过类型推断,分析出变量的类型;
  • 在写 TypeScript 代码的一个重要宗旨就是每个变量,每个对象的属性类型都应该是固定的,如果你推断就让它推断,推断不出来的时候你要进行注释
function getTotal(one:number, two:number){
  return one + two;
}
const total = getTotal(1,2);

函数参数和返回类型定义

  • 函数有返回值
function getTotal(one:number, two: number): number{
  return one + two;
}
const total = getTotal(1,2)
  • 函数无返回值,void
function sayHello(): void {
  console.log('hello-);
}
  • never 返回值类型 函数抛出异常 || 死循环情况
function errFunc(): never {
  throw new Error();
  console.log('hello~);
}

function forNever(): never{
  while(true){}
  console.log(hl-);
}
  • 函数参数为对象(解构)时
function add({one, two}: {one: number, two: number}): number {
  return one + two;
}
const total = add({one:1, two:2});

function getNumber({one}: {one: number}): number{
  return one;
}
const  num = getNumber({one:8});

数组类型的定义

  • 一般数组类型的定义
const numberArr = [1,2,3] // ts可以自己推断,不加类型也可以
const numberArr: number[] = [1,2,3];
const strArr: string[] = ['1', '2'];
const undefinedArr: undefined[] = [undefined, undefined];
const arr: (number | string)[] = [1,'2',3];

  • 数组中对象类型的定义
const arr: {name: string, age:number}[] = [
  {name:'ssd', age:12},
  {name:'sdsd, age: 123},
]
  • 类型别名(也可以实现代码重用),等价于上面写法
type ArrItem = {name: string, age: number}
const arr: ArrItem[] = [
  {name:'ds', age:12},
  {name:'233', age:8},
]
  • class 类定义也可以
class ArrItem {
  name: string,
  age: number,
}

const arr: ArrItem[] = [
  {name: '12', age: 12},
  {name:'dfdf', age:89},
]

元组的使用和类型约束

  • 解决多个类型时候类型注解不准确的问题,如希望得到这种const aa: (string | number)[] = ['ss', 'sdw', 12];
    const aa: (string | number)[] = [12, 'sdw', 12];这种也不会报错,,此时可借助元组解决问题;
  • 元组:const arr: [string, string, number] = ['ss', 'sdsd', 18];

interface

  • 接口,就是用来规范类型的。
  • 把多个重复的类型注解,定义成统一的接口;
interface Person {
  name: string,
  age: number,
  height: number,
}

const getPerson = (person: Person) => {
  peraon.age < 24 && person.height > 160 && console.log(person.name + 'ok');
  peraon.age > 24 && person.height < 160 && console.log(person.name + 'no ok');
}
  • 接口和类型别名的区别:
    • 类型别名可以直接给类型如type Person = string;,而接口必须代表对象,即初始化 person 时,必须写成这种形式const person = {name: 'ss', age: 12, height: 179}
  • 接口可以定义非必选值类型
interface Person {
  name: string;
  age: number;
  height?: number;
}

  • 接口允许加入任意值
interface Person {
  name: string;
  age: number;
  height?: number;
  // 任意值,属性名字是字符串类型,属性值可以是任何类型
  [propname: string]: any,
}

const person = {
  name: 'kk',
  age: 12,
  sex: 'nv'
}
  • 接口里的方法,接口不仅可以存属性,还可以存方法
interface Person {
  name: string;
  age: number;
  height?: number;
  [propname:string]: any;
  say(): string;
}

const person = {
  name: 'kk',
  age: 13,
  height: 190,
  say(){
    return 'hello~';
  }
}
  • 接口和类的约束,实现 && 继承
class XY implements Person {
  name = 'k';
  age = '13';
  height = 120;
  say() {
    return 'hello--'
  }
}
interface Teacher extends Person {
  teach(): string;
}

const person = {
  name: 's',
  age: 12,
  height: 190,
  say() {
    return 'kk'
  },
  teach() {
    return 'mm'
  }
}

const getResume = (person: Teacher) = > {
  console.log('kkk');
}

  • 基本使用
class Person {
  content = "hi";
  sayHi(){
    return this.content;
  }
}

const person = new Person();
console.log(person.sayHi());
  • 类的重写:子类可以重新编写父类里边的代码;
class XY extends Person {
  sayHi(){
    return 'hi, girl';
  }
  sayWorld() {
    return 'hello world'
  }
}
  • super:使用 super 关键字,它代表父类中的方法
class XY extends Person {
  sayHi(){
    return super.sayHi() + "---你好世界";
  }
}

类的访问类型: public/protected/private

  • public, 公共的,允许在类的内部和外部被调用.
class Person {
    public name:string;
    public sayHello(){
        console.log(this.name + 'say Hello')
    }
}
//-------以下属于类的外部--------
const person = new Person()
person.name = 'jspang.com'
person.sayHello()
console.log(person.name)
  • private, 私有的,只允许在类的内部使用
class Person {
    private name:string;
    public sayHello(){
        console.log(this.name + 'say Hello')  //此处不报错
    }
}
//-------以下属于类的外部--------
const person = new Person()
person.name = 'jspang.com'    //此处报错
person.sayHello()
console.log(person.name)  //此处报错
  • protected, 允许在类内及继承的子类中使用
class Person {
    protected name:string;
    public sayHello(){
        console.log(this.name + 'say Hello')  //此处不报错
    }
}

class Teacher extends Person{
    public sayBye(){
        this.name;
    }
}

类的构造函数

  • 构造函数:在类被初始化时候自动执行的一个方法。
  • Person 类,类的里边定义一个 name,但是 name 我们并不给他值,然后我们希望在 new 出对象的时候,直接通过传递参数的形式,给 name 赋值,并打印出来。这时候我们就需要用到构造函数了,构造函数的关键字是 constructor
class Person {
  public name: string;
  constructor(name: string){
    this.name = name;
  }
}

const person = new Person('sds');
console.log(person.name);
class Person {
  constructor(public name: string){}
}
const person = new Person('kk');
console.log(person.name);
  • 类继承中的构造器写法
class Person {
  constructor(public name: string) {}
}
class Teacher extends Person {
  constructor(public age: number){
    super('js')
  }
}
const teacher = new Teacher(19);
console.log(teacher.age);
console.log(teacher.name);
  • 这就是子类继承父类并有构造函数的原则,就是在子类里写构造函数时,必须用 super()调用父类的构造函数,如果需要传值,也必须进行传值操作。就是是父类没有构造函数,子类也要使用 super()进行调用,否则就会报错.

Getter/Setter/static

  • 访问类型的用途:封装一个属性,然后通过 Getter 和 Setter 的形式来访问和修改这个属性

类的只读属性和抽象类

  • readonly
class Person {
  public readonly name: string;
  constructor(name: string){
    this.name = name;
  }
}
  • abstract
abstract class Person {
  abstract skill()
}

class A extends Person {
  skill(){
    console.log('A 技能');
  }
}

class B extends Person {
  skill(){
    console.log('B 技能');
  }
}

class C extends Person {
  skill(){
    console.log('C 技能');
  }
}

tsconfig.json

  • tsc --init 生成
  • 使得配置文件生效,使用 tsc 命令,而不是 ts-node 命令
  • 写配置文件时有个坑需要注意,就是配置文件不支持单引号,所以里边都要使用双引号
  • include 属性是用来指定要编译的文件的,
  • exclude 是不包含,除什么文件之外的文件才进行编译。
  • compilerOptions 配置项:告诉 TypeScript 具体如何编译成 js 文件的

联合类型 && 类型保护

  • 联合类型:一个变量可能有两种或两种以上的类型。 '|'表示。 如const a: Waiter | Teacher;a 可能是 Waiter 类型(有 wa 方法),也可能是 Teacher 类型(有 ta 方法),如果直接调用 wa 方法,是会报错的,因为 a 也可能是 Teacher 类型就没有 wa 方法,此时就需要用到类型保护了。
  • 类型保护
  1. 类型断言:通过断言的方式确定传递过来的准确值,
  2. in 语法
  3. typeof 语法
  4. instanceof 语法
  • 类型保护-类型断言
interface Waiter {
  aa: boolean;
  say: () => {};
}

interface Teacher {
  aa: boolean;
  skill: () => {};
}

function judgeWho(a: Waiter | Teacher) {
  // aa为true说明是Waiter类型
  if (a.aa) {
    (a as Waiter).say();
  } else {
    (a as Teacher).skill();
  }
}
  • 类型保护-in 语法
function judgeWho(a: Waiter | Teacher) {
  if ('skill' in a) {
    a.skill();
  } else {
    a.say();
  }
}
  • 类型保护-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 addObj(first: object | NumberObj, second: object | NumberObj) {
  if(first instanceof NumberObj && second instanceof NumberObj) {
    return first.count + second.count;
  }
  return 0;
}

Enum 枚举类型

enum Status {
  a,
  b,
  c
}

function get(status: any) {
  if(status === Status.a){
    return 'aaaa'
  } else if (status === Status.b) {
    return 'bbbb'
  } else if (status === Status.c) {
    return 'cccc'
  }
}

const result = get(Status.a)
console.log(result);

泛型

  • 通用-泛指的类型,<>包裹,如来作泛型的表示
  • 泛型中数组的使用
const arr: number[] = [1,2,3]

const arr: Array<number> = [1,2,3] // 泛型
  • 一个函数可以定义多个泛型,
function join<T, P>(first: T, second: P) {
  return `${first}${second}`;
}
join<number, string>(1, '2');
  • 类型约束
// 泛型约束
class A<T extends number | string> {}

搭建继承的 TS 开发环境

  1. 建立好文件夹后,打开 VSCode,把文件夹拉到编辑器当中,然后打开终端,运行 npm init -y,创建 package.json 文件。
  2. 生成文件后,我们接着在终端中运行 tsc -init,生成 tsconfig.json 文件。
  3. 新建 src 和 build 文件夹,再建一个 index.html 文件。
  4. 在 src 目录下,新建一个 page.ts 文件,这就是我们要编写的 ts 文件了。
  5. 配置 tsconfig.json 文件,设置 outDir 和 rootDir(在 15 行左右),也就是设置需要编译的文件目录,和编译好的文件目录。
  6. 然后编写 index.html,引入,当让我们现在还没有 page.js 文件。
  7. 编写 page.ts 文件,加入一句输出 console.log('jspang.com'),再在控制台输入 tsc,就会生成 page.js 文件
  8. 再到浏览器中查看 index.html 文件,如果按 F12 可以看到 jspang.com,说明我们的搭建正常了。

命名空间

  • namespace moduleName {}
  • 提供的类似模块化开发的语法,让全局变量减少了很多,实现了基本的封装,减少了全局变量的污染。

Parcel 打包 ts

  • yarn add --dev parcel@next

示例

// 变量声明,给JavaScript中的基础类型使用的
let val:number = 1;
let val2:string = "1";
let val3:boolean = true;

// 接口,给对象这种复杂的类型使用的,当我们有一个对象的时候,可以通过接口整体的来描述这个对象
interface person {
    name: string,
    age?: number, //表示age这个属性可能存在,也可能不存在
}
// xm是一个对象,而JavaScript中没有xm这种数据类型,我们定义的接口person就可以用来描述xm的数据类型
const xm:person = {
    name: 'kk',
    age: 16
}

// 当给函数添加了类型后,调用的时候,就可以清楚的看到这个函数需要什么类型的参数,会返回什么样的参数,

// 函数
interface Fun {
    (num: number, str: string): string
}

const fun: Fun = (num, str) => {
    return '123'
}

// 类
class Person {
    name: string,
    constructor(name: string) {
        this.name = name;
    }
}

let xx = new Person('kk');

// vue中使用
<script setup lang="ts">
    // ts中,定义count的时候,默认值给的是数字1,对count的value赋值也应该是数值
    let count = ref(1);
    count.value = 2;

    // 定义一个字符串或数字类型的响应式变量
    let count = ref<string | number>('1');
    count.value = 1;

    interface Person {
        name: string,
        age: number
    }

    let person = reactive<Person>({
        name: 'xx',
        age: 18
    })

    let person2: Person = reactive({
        name: 'xx',
        age: 14
    })

    let person3 = reactive({
        name: 'xx',
    }) as Person;

    // 在Vue中还有props和emits也可以申明变量,通过泛型的方式来添加类型

    // ts不认识.vue文件,所以需要添加一个声明文件,在根目录下新建env.d.ts文件
    declare module '*.vue' {
        import type { DefineComponent } from 'vue';
        const component: DefineComponent<{}, {}, any>
        export default component;
    }


    // 泛型
    export function ref<T>(value: T): T
    // 也可以不用插入泛型,会自动根据传入的参数进行类型推导出来
    let str = ref('string'); // ref<string>('string');
    let num = ref(123); // ref<number>(123);
</script>






ts-技术胖
ts-技术胖
Vue3
posted @ 2019-09-01 22:57  安静的嘶吼  阅读(318)  评论(0编辑  收藏  举报