TypeScript 个人笔记(一)

173 阅读7分钟

1 ts 安装和编译

  • 第一步 新建一个空文件夹用来学习 ts
  • 第二步 全局安装 ts 和 ts-node
npm i typescript -g //全局安装ts
npm i -g ts-node //全局安装ts-node

  • 第三步 生成 tsconfig.js 配置文件
tsc --init

我们就先按照自动生成的 tsconfig 配置项去使用 里面的配置咱们可以先不去管他 后续熟练了再去配置

  • 第四步 在项目下新建一个index.ts 直接写入 pple
const st: string = "hi";
console.log(st);

  • 第五步 编译 ts 为 js 在控制台(终端)输入命令
tsc index.ts

项目下出现了一个同名的 index.js 文件 至此我们已经可以把 ts 文件编译成 js 文件了

不过到这里聪明的小伙伴就会发现了 我们全局安装的 ts-node 有什么作用呢 其实这个包是帮助我们在不需要编译成 js 的前提下就可以直接执行 ts 代码 比如 我们在控制台输入

ts-node index.ts

可以看到我们打印的hi已经输出了

那可能 还有的小伙伴会发现 我们每次改动都要手动去执行编译 这样很麻烦 其实我们可以加一个参数来实现每次文件变动 ts 帮我们自动编译成 js 的效果

tsc --watch index.ts

字符

const a: string = 'holle world'

布尔

const flga: boolean = false

数字

const num: number = 123

枚举

enum Color {
    red,
    green,
    balck
}
const b: Color = Color.green
console.log(b); // 1 
enum Air {
    O,
    N = 10,
    H
}
const c: Air = Air.H
console.log(c);//11
const e: Air = Air.N
console.log(e);//10

const d: Air = Air.O
console.log(d);//0
// 字符串枚举 每个都需要声明
enum All {
    Css = 'red',
    Body = 'green',
    Div = 'blue'
}
const C: All = All.Css
console.log(C); // red

数组

const arr: number[] = [1, 2, 3]
console.log(arr); // [1, 2, 3]

const arr1: Array<string> = ['e', 'b', 'w']
console.log(arr1); //['e', 'b', 'w']

元组类型(tuple)

在 TypeScript 的基础类型中,元组( Tuple )表示一个已知数量和类型的数组 其实可以理解为他是一种特殊的数组

const arr2: [string, number] = ['h', 2]
console.log(arr2); //['h', 2]

Symbol

我们在使用 Symbol 的时候,必须添加 es6 的编译辅助库 需要在 tsconfig.json 的 libs 字段加上ES2015 Symbol 的值是唯一不变的

  const sy1=Symbol('hi')
  const sy2=Symbol('hi')
  console.log(Symbol('hi')===Symbol('hi'));

任意类型(any)

任何类型都可以被归为 any 类型 这让 any 类型成为了类型系统的 顶级类型 (也被称作 全局超级类型)
TypeScript 允许我们对 any 类型的值执行任何操作 而无需事先执行任何形式的检查
一般使用场景:
第三方库没有提供类型文件时可以使用 any
类型转换遇到困难或者数据结构太复杂难以定义
不过不要太依赖 any 否则就失去了 ts 的意义了

const dom: any = document.getElementById('root')
console.log(dom);

// null 和 undefined
//undefined 和 null 两者有各自的类型分别为 undefined 和 null
let n: null = null
let u: undefined = undefined

Unknown 类型

unknown 和 any 的主要区别是 unknown 类型会更加严格 在对 unknown 类型的值执行大多数操作之前 我们必须进行某种形式的检查,而在对any 类型的值执行操作之前 我们不必进行任何检查
所有类型都可以被归为 unknown 但unknown类型只能被赋值给 any 类型和 unknown 类 型本身而 any 啥都能分配和被分配

let val: unknown;
val = true
val = 42
val = 'hi'
val = []
val = {}
let val1: unknown = val
let val2: any = val
// let val3:boolean = val // error
// let val4:number = val // error
// let val3:string = val // error

void 类型

void 表示没有任何类型 当一个函数没有返回值时 TS 会认为它的返回值是 void 类型

function hi(age: string): void { }

never 类型

never 一般表示用户无法达到的类型
例如never 类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型

function neverBack(): never {
    throw new Error('error')
}

never 和 void 的区别

void 可以被赋值为 null 和 undefined 的类型。 never 则是一个不包含值的类型。
拥有 void 返回值类型的函数能正常运行。拥有 never 返回值类型的函数无法正常返回, 无法终止,或会抛出异常。

BigInt 大数类型
使用 BigInt 可以安全地存储和操作大整数
我们在使用 BigInt 的时候 必须添加 ESNext 的编译辅助库需要在 tsconfig.json的 libs 字段加上ESNext
要使用1n需要 "target": "ESNext"
number 和 BigInt 类型不一样 不兼容

// const max1 = Number.MAX_SAFE_INTEGER; // 2**53-1
// console.log(max1 + 1 === max1 + 2); //true

// const max2 = BigInt(Number.MAX_SAFE_INTEGER);
// console.log(max2 + 1n === max2 + 2n); //false

// let foo: number;
// let bar: bigint;
// foo = bar; //error
// bar = foo; //error

object, Object 和 {} 类型

// object 类型用于表示非原始类型
let objectCase: object
objectCase=1; //error Type 'number' is not assignable to type 'object'.
objectCase='www'; //Type 'string' is not assignable to type 'object'.
objectCase=true; // Type 'boolean' is not assignable to type 'object'.
objectCase=null; // error
objectCase=undefined; //error
objectCase = {}; // ok

大 Object 代表所有拥有 toString、hasOwnProperty 方法的类型
所以所有原始类型、非原始类型都可以赋给 Object(严格模式下 null 和 undefined 不可以)

let ObjectCase: Object
ObjectCase = 1; //ok.
ObjectCase = 'www'; //ok'.
ObjectCase = true; // ok'.
// ObjectCase=null; // error
// ObjectCase=undefined; //error
ObjectCase = {}; // ok

空对象类型和大 Object 一样 也是表示原始类型和非原始类型的集合

let simpleCase: {}
simpleCase = 1; //ok.
simpleCase = 'www'; //ok'.
simpleCase = true; // ok'.
// simpleCase=null; // error
// simpleCase=undefined; //error
simpleCase = {}; // ok

类型推论

指编程语言中能够自动推导出值的类型的能力 它是一些强静态类型语言中出现的特性 定义时未赋值就会推论成 any 类型 如果定义的时候就赋值就能利用到类型推论

let active; //any
let num1 = 9527;//为number类型
let str = '高级伴读书童';//为stringr类型

联合类型

联合类型(Union Types)
表示取值可以为多种类型中的一种 未赋值时联合类型上只能访问两个类型共有的属性和方法

let zhangsan: string | number;
// console.log(zhangsan.toString());
zhangsan = 1
console.log(zhangsan.toFixed(2));
zhangsan = 'shark'
console.log(zhangsan.length);

类型断言

有时候你会遇到这样的情况,你会比 TypeScript 更了解某个值的详细信息。
通常这会发生在你清楚地知道一个实体具有比它现有类型更确切的类型。其实就是你需要手动告诉
ts 就按照你断言的那个类型通过编译(这一招很关键 有时候可以帮助你解决很多编译报错)

// 尖括号 语法
 let value:any = 'We are idealistic'
let strLength:number=(<string>value).length
 console.log(strLength);

// as 语法
let value: any = 'We are idealistic'
let strLength: number = (value as string).length
console.log(strLength);

以上两种方式虽然没有任何区别,但是尖括号格式会与 react 中 JSX 产生语法冲突,
因此我们更推荐使用 as 语法。

非空断言

在上下文中当类型检查器无法断定类型时
一个新的后缀表达式操作符 ! 可以用于断言操作对象是非 null 和非 undefined 类型

let blo: null | undefined | string
blo!.toString() //ok
// blo.toString() //error

面量类型

在 TypeScript 中,字面量不仅可以表示值,还可以表示类型,即所谓的字面量类型。
目前,TypeScript 支持 3 种字面量类型:字符串字面量类型、数字字面量类型、布尔字面量类型,
对应的字符串字面量、数字字面量、布尔字面量分别拥有与其值一样的字面量类型, 具体示例如下:

let strValue: 'ningwang' = 'ningwang'
let strNum: 123 = 123
let strBlo: true = true

类型别名

类型别名用来给一个类型起个新名字

type flag = string | number;

function hello(value: flag) { }

交叉类型

交叉类型是将多个类型合并为一个类型。
通过 & 运算符可以将现有的多种类型叠加到一起成为一种类型,它包含了所需的所有类型的特性

 type Flag1 = { x: number };
 type Flag2 = Flag1 & { y: string };

 let flag3: Flag2 = {
   x: 1,
   y: "hello",
  active
};

类型保护

类型保护就是一些表达式,
他们在编译的时候就能通过类型信息确保某个作用域内变量的类型
其主要思想是尝试检测属性、方法或原型,以确定如何处理值

function typeStatus(input: string | number | boolean) {
    if (typeof input === "string") {
        return input + 1
    } else {
        if (typeof input === 'number') {
            return input += 2
        } else {
            return !input
        }
    }
}

interface Bird {
    fly: number;
}

interface Dog {
    leg: number;
}

in 关键字

interface Bird {
    fly: number;
}

interface Dog {
    leg: number;
}

function getNumber(value: Bird | Dog) {
    if ("fly" in value) {
        return value.fly;
    }
    return value.leg;
}

instanceof 类型保护

class Animal {
    name!: string;
}
class Bird extends Animal {
    fly!: number;
}
function getName(animal: Animal) {
    if (animal instanceof Bird) {
        console.log(animal.fly);
    } else {
        console.log(animal.name);
    }
}

自定义类型保护

通过 type is xxx这样的类型谓词来进行类型保护
例如下面的例子 value is object就会认为如果函数返回true 那么定义的 value 就是 object 类型

function isObject(value: unknown): value is object {
    return typeof value === "object" && value !== null;
}

function fn(x: string | object) {
    if (isObject(x)) {
          console.log(x);
    } else {
          console.log(x);
    }
}