当前位置:网站首页 > TypeScript编程 > 正文

typescript implements_typescript有必要学吗

踩坑经验汇总

阅读前请先熟读阅读Typescript HandBook

使用 Typescript 一定要清楚哪些是运行时代码哪些是类型代码

类型

Type 别名

普通、简单类型声明一律使用type

与 interface 两者的关键区别是 type 不能被重复使用加入新属性,但 interface 可以一直扩展

// type 不支持 extends,使用 = 设置类型 export type MicroAppState = { 
    isError: boolean mounted: boolean loading: boolean resetting: boolean } // type 可以与其他type扩展出新类型 如 export type Result = { 
    context: { 
    warnings: HTMLElement[] references: HTMLElement[] elementsById: HTMLElement[] } } & OtherType 

interface

复杂的、可扩展的、多重继承使用interface

interface Diagram { 
    // 构造函数可以这么写 constructor(options: anyType) } // interface的扩展使用extends关键字 interface BaseViewer extends Diagram { 
    // 构造函数也可以这么写 new (options: anyType) newMethod: () => void } 

interface 没法实现 Utility type 如以下

type Person = { 
    name: string age: number } // 没有age的Person类型实现 const onlyNamePerson: Omit<Person, 'age'> = { 
    name: 'xaoMing' } // 没有名字和age的Person类型实现 const smPerson: Omit<Person, 'name' | 'age'> = { 
   } 

any

Typescript 中使用做多的类型,任何不确定的类型都会用 any 表示

实际开发中我们尽量不实用 any,大量的使用 any 就没有必要使用 ts 开发了

// any会让下面的代码执行都成立 let obj: any = { 
    x: 0 } obj.foo() obj() obj.bar = 100 obj = 'hello' const n: number = obj 

as

类型断言,就是告诉编译器我确定这家伙是这种类型

  • as 断言
// as 语法 let someValue: unknown = 'this is a string' let strLength: number = (someValue as string).length 
  • 尖括号断言(无法与 jsx 配合使用)
let someValue: unknown = 'this is a string' let strLength: number = (<string>someValue).length 

unknown

unknown 指的是不可预先定义的类型
unknown 的一个使用场景是,避免使用 any 作为函数的参数类型而导致的静态类型检查 bug
unknown 类型必须先转为一个确定类型后才能调用其属性或方法

return ( lang || (window as unknown as GLocaleWindow).g_locale || navigator.language ) 

void

返回类型,一个方法没有任何返回值时

// 一个接受字符串的不返回任何值的函数 type someMethod = (type: string) => void 

never

返回类型,没法正常结束返回的类型

一般用在报错、死循环、switch 拖底中做返回类型,新手小白唔用

// throw error 返回值是never function foo(): never { 
    throw new Error('error message') } // 这个死循环的也会无法正常退出 function foo(): never { 
    while (true) { 
   } } // Error: 这个无法将返回值定义为never,因为无法在静态编译阶段直接识别出 function foo(): never { 
    let count = 1 while (count) { 
    count++ } } // Exhaustiveness checking 穷尽性检查 interface Triangle { 
    kind: 'triangle' sideLength: number } type Shape = Circle | Square | Triangle function getArea(shape: Shape) { 
    switch (shape.kind) { 
    case 'circle': return Math.PI * shape.radius  2 case 'square': return shape.sideLength  2 default: const _exhaustiveCheck: never = shape // Type 'Triangle' is not assignable to type 'never'. return _exhaustiveCheck } } 

Literal Types

字面量类型, 使用了特定字符串或数字的类型

// let 和 const 声明的类型不同 // changingString的类型为 string; let changingString = 'Hello World' // constantString 的类型为 'Hello World'; const constantString = 'Hello World' // 无法通过编译 constantString = 'howdy' 

字面量类型在处理字符串数字枚举值时很有效,但需要做转换来去掉类型问题

// 字面量类型无法识别两个GET字符串是相同的 const req = { 
    url: 'https://example.com', method: 'GET' } // 报错 Argument of type 'string' is not assignable to parameter of type '"GET" | "POST"'. handleRequest(req.url, req.method) // 修改方法1 使用 as 转换 const req = { 
    url: 'https://example.com', method: 'GET' as 'GET' } handleRequest(req.url, req.method as 'GET') // 修改方法2 使用 const 转换整个对象为字面量类型 const req = { 
    url: 'https://example.com', method: 'GET' } as const handleRequest(req.url, req.method) 

操作符

?

可选变量

对象可不包含该 可选变量

interface PaintOptions { 
    shape: Shape xPos?: number yPos?: number } function paintShape(opts: PaintOptions) { 
    // ... } const shape = getShape() paintShape({ 
    shape }) paintShape({ 
    shape, xPos: 100 }) paintShape({ 
    shape, yPos: 100 }) paintShape({ 
    shape, xPos: 100, yPos: 100 }) 

可选参数

不传也不会报错

function f(x?: number) { 
    // ... } f() // OK f(10) // OK 

!

非空断言操作符

function liveDangerously(x?: number | null) { 
    // 使用!告诉编译器我是真的 console.log(x!.toFixed()) } 

keyof

keyof 可以获得一个类型所有的键并返回一个联合类型

type Person = { 
    name: string age: number } // PersonKey得到的类型为 'name' | 'age' type PersonKey = keyof Person // 使用案例 function getValue(p: Person, k: PersonKey) { 
    // 如果k不如此定义,则无法以p[k]的代码格式通过编译 return p[k] } 

typeof

typeof 获取一个实际对象的类型

const me: Person = { 
    name: 'gzx', age: 16 } // { name: string, age: number | undefined } type P = typeof me // 可以通过编译 const you: typeof me = { 
    name: 'mabaoguo', age: 69 } 

in

in 只能用在类型的定义中,可以对枚举类型进行遍历

// 这个类型可以将任何类型的键值转化成number类型 type TypeToNumber<T> = { 
    [key in keyof T]: number } const obj: TypeToNumber<Person> = { 
    name: 10, age: 10 } 

泛型

泛型可以用在普通类型定义,类定义、函数定义上,如下:

// 普通类型定义 type Dog<T> = { 
    name: string; type: T } // 普通类型使用 const dog: Dog<number> = { 
    name: 'ww', type: 20 } // 类定义 class Cat<T> { 
    private type: T constructor(type: T) { 
    this.type = type } } // 类使用 const cat: Cat<number> = new Cat<number>(20) // 或简写 const cat = new Cat(20) // 函数定义 function swipe<T, U>(value: [T, U]): [U, T] { 
    return [value[1], value[0]] } // 函数使用 swipe<Cat<number>, Dog<number>>([cat, dog]) // 或简写 swipe([cat, dog]) 

泛型默认值

type Dog<T = string> = { 
    name: string; type: T } const dog: Dog = { 
    name: 'ww', type: 'hsq' } 

泛型约束

在方法内需要调用泛型内的特定属性方法,需要使用 extends 执行泛型约束

interface Lengthwise { 
    length: number } function loggingIdentity<Type extends Lengthwise>(arg: Type): Type { 
    // 使用extends 继承自含有length的对象就不会报错了 console.log(arg.length) return arg } 

泛型条件

高级玩法

Conditional Types

方法泛型

type off = <T, V>(events: T | string | string[], callback: V) => void 

JSX 泛型

import {Select} from 'antd' export default (props) => { return <Select<string> {...props}> } 

泛型工具

常用于表单提交,将已经定义好的类型抽像成表单提交的实际内容定义

// 将类型属性全部变为可选的 Partial<T> // 将类型属性全部变为必选的 Required<T> // 将 T 类型中的 K 键列表提取出来,生成新的子键值对类型。 Pick<T, K> const bird: Pick<Animal, "name" | "age"> = { 
    name: 'bird', age: 1 } // 在 T 类型中,去除 T 类型和 U 类型的交集,返回剩余的部分 Exclude<T, U> // 去除类型 T 中包含 K 的键值对 Omit<T, K> // 获取 T 类型(函数)对应的返回值类型 ReturnType<T> 

用于声明普通对象

Record<K, T> type ELDrawerPropsType = { 
    onOk: (fieldsValue: Record<string, string>, index: number) => void; }; 

声明

声明文件

Typescript 中使用.d.ts结尾的文件作为声明文件

声明文件应放置于项目跟路径的typings目录内

delare

声明关键字,声明结果均为全局声明

// 全局声明变量 declare var declare let declare const // 全局声明方法 declare function // 全局声明类 declare class { 
   } // 全局声明枚举 declare enum // 全局声明类型 declare type // 全局声明接口 declare interface { 
   } // 全局声明命名空间 declare namespace // 全局声明模块 declare module 

namespace

namespace 用来解决工程过大命名冲突的问题,可以跨文件使用

对外可通过 export 向外导出作为模块使用(deprecated)

// a.d.ts declare namespace FescoTechTao { 
    type A; } // b.d.ts declare namespace FescoTechTao { 
    type B; } 

module

module 用来定义外部 ES 模块,可跨文件使用

// canvas.d.ts declare module 'diagram.js' { 
    export interface Canvas { 
   } } // eventBus.d.ts declare module 'diagram.js' { 
    export interface EventBus { 
   } } // main.ts import { 
    Canvas, EventBus } from 'diagram.js' 

module 可以用来定义静态模块

declare module 'slash2' declare module '*.css' declare module '*.less' declare module '*.scss' declare module '*.sass' declare module '*.svg' declare module '*.png' declare module '*.jpg' declare module '*.jpeg' declare module '*.gif' declare module '*.bmp' declare module '*.tiff' declare module 'omit.js' declare module '*.xml' { 
    // Change this to an actual XML type const value: string export default value } 

module 可以用来改写 npm 包中的模块定义

type PutResolveType = { 
    resolve: <A extends AnyAction>(action: A) => Promise<void> } type PutType = <A extends AnyAction>(action: A) => any declare module 'dva' { 
    export interface EffectsCommandMap { 
    put: PutResolveType & PutType call: Function select: Function take: Function cancel: Function [key: string]: any } } 

module 可以补充声明没有编写声明文件的 npm 包

declare module 'dva-model-extend' declare module 'bpmn-js-properties-panel' declare module 'bpmn-js-properties-panel/lib/provider/camunda' declare module 'camunda-bpmn-moddle' declare module 'camunda-bpmn-moddle/resources/camunda' 

module 可以扩展其他全局对象的属性方法

declare global { 
    interface Window { 
    ga: ( command: 'send', hitType: 'event' | 'pageview', fieldsObject: GAFieldsObject | string ) => void reloadAuthorized: () => void bpmnInstances: BpmnInstancesType } interface Console { 
    logModel: (namespace: string, expand?: boolean) => void logModelState: (namespace: string, expand?: boolean) => void } } declare module NodeJS { 
    interface Global { 
    host: string href: string _cookies: string _navigatorLang: string } } 

使用 module 给 vue 扩展原型链

import type { 
    AxiosInstance } from 'axios' declare module 'Vue/types/vue' { 
    interface Vue { 
    $axios: AxiosInstance } } 

/// 三斜线指令

///<reference types=“UMDModuleName/globalName” /> ts 早期模块化的标签, 用来导入依赖, ES6 广泛使用后, 在编写 TS 文件中不推荐使用,使用 import 代替

到此这篇typescript implements_typescript有必要学吗的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • typescript namespace module_编程项目2024-11-06 12:25:07
  • typescript基础语法_深入理解typescript2024-11-06 12:25:07
  • typescript教程视频_typescript入门教程2024-11-06 12:25:07
  • typescript写法_typescript入门教程2024-11-06 12:25:07
  • 探索 TypeScript 技术世界:全面学习指南2024-11-06 12:25:07
  • TypeScript编程中常用的通用方法_typescript 教程2024-11-06 12:25:07
  • TypeScript入门案例2024-11-06 12:25:07
  • 【前端-TypeScript】TypeScript学习思维导图-一图看完《TypeScript编程》2024-11-06 12:25:07
  • typescript的作用_typescript有必要学吗2024-11-06 12:25:07
  • typescript interface和type的区别_typescript高级类型声明2024-11-06 12:25:07
  • 全屏图片