本文总结一下TypeScript类型声明的书写,很多时候写TypeScript不是问题,写类型就特别纠结,我总结下,我在使用TypeScript中遇到的问题。如果你遇到类型声明不会写的时候,多看看lodash的声明,因为lodash对数据进行各种变形操作,所以你能遇到的,都有参考示例。

基本类型

// 变量

const num: number = 1;

const str: string = 'str';

const bool: boolean = true;

const nulls: null = null;

const undefine: undefined = undefined;

const symbols: symbol = Symbol('symbal');

const any: any = 'any types'; // typescript的any类型,相当于什么类型约束都没有

数组

// 数组: 推荐使用T[]这种写法

const nums: number[] = [1, 2, 3, 4];

// 不推荐:Array泛型写法,因为在JSX中不兼容,所以为了统一都使用T[]这种类型

const strs: Array = ['s', 't', 'r'];

const dates: Date[] = [new Date(), new Date()];

数组的concat方法,返回类型为never[]问题

// 数组concat方法的never问题

// 提示: Type 'string' is not assignable to type 'never'.

const arrNever: string[] = [].concat(['s']);

// 主要问题是:[]数组,ts无法根据上下文判断数组内部元素的类型

// @see https://github.com/Microsoft/TypeScript/issues/10479

const fixArrNever: string[] = ([] as string[]).concat(['s']);

接口

接口是 TypeScript 的一个核心知识,它能合并众多类型声明至一个类型声明:

而且接口可以用来声明:函数,类,对象等数据类型

interface Name {

first: string;

second: string;

}

let username: Name = {

first: 'John',

second: 'Doe'

};

any、null、undefined、void类型

// 特殊类型

const any: any = 'any types'; // typescript的any类型,相当于什么类型都没写

let nobody: any = 'nobody, but you';

nobody = 123;

let nulls: number = null;

let bool: boolean = undefined;

// void

function printUsername (name: string): void {

console.log(name);

}

联合类型

联合类型在option bags模式场景非常实用,使用 **| **来做标记

function options(opts: {

types?: string;

tag: string | number;

}): void {

}

交叉类型

最典型的使用场景就是继承和mixin,或者copy等操作

// 交叉类型:如果以后遇到此种类型声明不会写,直接看Object.assign声明写法

function $extend(first: T, second: U): T & U {

return Object.assign(first, second); // 示意而已

}

元组 tuple

元组很少使用

let nameNumber: [string, number];

// Ok

nameNumber = ['Jenny', 221345];

// Error

// nameNumber = ['Jenny', '221345'];

let tuple: [string, number];

nameNumber = ['Jenny', 322134];

const [usernameStr, uselessNum] = nameNumber;

type的作用

ype用来创建新的类型,也可以重命名(别名)已有的类型,建议使用type创建简单类型,无嵌套的或者一层嵌套的类型,其它复杂的类型都应该使用interface, 结合implements ,extends实现。

type StrOrNum = string | number;

// 使用

let sample: StrOrNum;

sample = 123;

sample = '123';

// 会检查类型

sample = true; // Error

实践中遇到的问题

第三方库没有提供声明d.ts文件

如果第三方库没有提供声明文件,第一时间去微软官方的仓库https://github.com/borisyankov/DefinitelyTyped 查找,或者在npmjs.com上搜索@types/依赖的模块名大部分情况都可以找到。

手动添加声明文件

声明文件一般都是统一放置在types文件夹下

// 例子: types/axios.d.ts

declare module 'axios'; // 这里的axios声明为any类型

全局变量

例如一些库直接把在window上添加的全局变量

// globals.d.ts

// 例子:jQuery,现实中jQuery是有.d.ts

declare const jQuery: any;

declare const $: typeof jQuery;

非JavaScript资源

在前端工程中,import很多非js资源,例如:css, html, 图片,vue, 这种ts无法识别的资源时,就需要告诉ts,怎么识别这些导入的资源的类型。

// 看看vue怎么处理的:shims-vue.d.ts

declare module '*.vue' {

import Vue from 'vue';

export default Vue;

}

// html

declare module '*.html';

// css

declare module '*.css';

强制类型转换

有时候遇到需要强制类型转换,尤其是对联合类型或者可选属性时。

// 第一种:使用<>括号

const convertArrType: string[] = >[].concat(['s']);

// 第二种:使用as关键字

const fixArrNever: string[] = ([] as string[]).concat(['s']);

建议使用第二种,因为兼容JSX,第一种官方也不推荐了,虽然它是合法的。

可选属性和默认属性

API中提供的参数很多都有默认值,或者属性可选,怎么书写呢?

class Socket {}

// 联合类型

export type SocketType = 'WebSocket' | 'SockJs';

export interface SocketOptions {

type: SocketType;

protocols?: string | string[]; // 可选

pingMessage: string | (() => string); // 联合类型,可以为string或者函数

pongMessage: string | (() => string);

}

// 默认值

export function eventHandler = (

evt: CloseEvent | MessageEvent | Event,

socket: Socket,

type = 'WebSocket' // 默认值

) => any;

独立函数怎么声明类型

刚开始我也很纠结这个问题,我就是一个独立的函数,怎么声明类型呢?尤其是写事件处理函数的API时。

class Socket {}

// 函数的声明方式

export type SocketEventHandler = (

evt: CloseEvent | MessageEvent | Event,

socket: Socket

) => any;

const eventHandler: SocketEventHandler = (evt, socket) => {

}

// 可选参数和rest参数

let baz = (x = 1) => {};

let foo = (x: number, y: number) => {};

let bar = (x?: number, y?: number) => {};

let bas = (...args: number[]) => {};

索引属性类型声明

JavaScript中的对象都可以使用字符串索引直接取属性或者调用方法,TypeScript中也有相应的类型声明方法。

type Hello = {

hello: 'world';

// key只是一个形式属性名(类似形参一样)

[key: string]: string;

};

const greeting: Hello = {

hi: 'morning'

}

console.log(greeting['hi'])

动态添加的属性声明

有的时候我们只声明了一个基本的类型结构,然后后续有扩展的情况 ,尤其时二次封装时的options。

interface AxiosOptions {}

type AjaxOptions = {

axiosOptions: AxiosOptions;

// 额外扩展的放入到单独的属性节点下

extraOptions: {

[prop: string]: any

};

};

type AjaxOptions1 = {

axiosOptions?: AxiosOptions;

// 不要这样写,因为axiosOptions拼写错误时,ts不会提示

// 尽量把后续扩展的属性,移动到独立的属性节点下

[prop: string]: any

};

const ajaxOptions: AjaxOptions1 = {

axiosOptions1: {}; // 本意是axiosOptions,但是ts不会提示

}

!的使用

! 标识符告诉ts编译器,声明的变量没有问题,再运行期不会报错。

class BaseSelect extends Vue {

options: string[]; // 这里会提示没有在constructor中初始化

created() {

this.options = ['inited']

}

}

class BaseSelect extends Vue {

options!: string[]; // 使用 ! 告诉编译器,我知道自己在做什么

created() {

this.options = ['inited']

}

}

this的使用

对于独立使用的函数,可以声明指定的调用上下文

class Handler {

info: string;

// 声明指定的this上下文

onClickBad(this: Handler, e: Event) {

// oops, used this here. using this callback would crash at runtime

this.info = e.message;

}

}

let h = new Handler();

uiElement.addClickListener(h.onClickBad); // error!

声明合并(扩展Vue声明)

来看看使用场景,扩展vue,在vue上添加全局的属性。

// vue的声明在 vue/types/vue.d.ts

declare module 'vue/types/vue' {

// 相当于Vue.$eventBus

interface Vue {

$eventBus: Vue;

}

// 相当于在Vue.prototype.$eventBus

interface VueConstructor {

$eventBus: Vue;

}

}

总结

TypeScript声明还有很多高级的用法,目前我也没有用到那么多,在我纠结不会写声明的时候,我就会看看别人的声明文件时怎么写的。

注意:尽量不要把解构和声明写在一起,可读性极差。

class Node {

onNodeCheck(checkedKeys: any, { // 解构

checked, checkedNodes, node, event,

} : { // 声明

node: any;

[key: string]: any;

}

) {

}

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

本条技术文章来源于互联网,如果无意侵犯您的权益请点击此处反馈版权投诉

本文系统来源:php中文网

typescript的类型描述_TypeScript类型声明书写详解相关推荐

  1. typescript索引类型_TypeScript类型声明书写详解

    本文总结一下TypeScript类型声明的书写,很多时候写TypeScript不是问题,写类型就特别纠结,我总结下,我在使用TypeScript中遇到的问题.如果你遇到类型声明不会写的时候,多看看lo ...

  2. MySQL5日期类型DATETIME和TIMESTAMP相关问题详解

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://lavasoft.blog.51cto.com/62575/280284 MySQ ...

  3. python中类的构成_Python中类型关系和继承关系实例详解

    本文详细介绍了Python中类型关系和继承关系.分享给大家供大家参考.具体分析如下: 如果一个对象A持有另一个对象B的ID,那么检索到A之后就可以检索到B,我们就说存在一个A到B的导航.这种导航关系使 ...

  4. python数值类型教程_Python数值类型 int、float、complex 详解

    Python数值类型 int.float.complex 详解 Python数值类型:int.float.complex 在Python程序中,int.float和complex是三种十分重要的数值类 ...

  5. swift. 扩展类添加属性_swift中的声明关键字详解

    原起 学习swift,swift中的关键字当然要了解清楚了,最近在网上看到了关于声明关键字的文章,整理记录一下. 关键字是类似于标识符的保留字符序列,除非用重音符号(`)将其括起来,否则不能用作标识符 ...

  6. 《TypeScript》入门与精通-.d.ts描述文件的使用和详解

    介绍 什么是描述文件?在回答这个问题之前,我们先思考这样一个问题,typescript和javascript原则上并不相通,那么在typescript出来之前所有的javascript是不是都不能使用 ...

  7. Typescript声明文件详解

    简介 声明文件是以.d.ts为后缀的文件,开发者在声明文件中编写类型声明,TypeScript根据声明文件的内容进行类型检查.(注意同目录下最好不要有同名的.ts文件和.d.ts,例如lib.ts和l ...

  8. Linux中光盘使用的文件类型,linux下mount命令使用详解---linux挂载光盘等文件系统...

    mount 命令详解 功能:加载指定的文件系统. 语法:mount [-afFhnrvVw] [-L标签] [-o选项] [-t文件系统类型] [设备名] [加载点] 用法说明:mount可将指定设备 ...

  9. 未能找到类型或命名空间名称_命名空间详解

    命名空间与类型有些相似,在类型中可以声明诸多成员:字段,属性,方法而在命名空间中可以声明:类,接口命名空间属于逻辑组合,用来对类型的功能进行逻辑分组成员根据相关性可以将name, age, sex成员 ...

最新文章

  1. Lock锁子类了解一下
  2. SAP成都研究院数字创新空间基于SAP C4C开发的一个智能服务原型项目
  3. placeholder=请输入用户名(六位数字加英文字母)
  4. 大型Javascript应用架构的模式(译文)
  5. dx 汇编dec_汇编语言——汇编指令
  6. Android Studio中导出数据库文件的方法总结
  7. 简单理解匈牙利KM算法
  8. dns和私人dns是什么意思?企业如何预防dns劫持?
  9. Entegris EUV 1010光罩盒展现极低的缺陷率,已获ASML认证
  10. Ubuntu 更换阿里云软件源
  11. 下载微信视频号里的视频一种方法
  12. 天正对应cad版本_天正CAD图形找不到可用的AutoCAD版本怎么办?
  13. 平均年薪50万,学好python程序员到底有多吃香?
  14. 突发奇想 之 古玩中的代码
  15. 如何通过划分VLAN,有效规划企业网ip地址!
  16. Hook技术之消息拦截(Windows Hook )
  17. doceker使用教程(一)
  18. 并发编程系列之Semaphore
  19. Mac 系统打开 word 显示全黑怎么处理
  20. angular技巧_提升Angular技能的5个技巧

热门文章

  1. 取一定范围内随机小数 c_算伪随机概率中C值的快捷方法
  2. Fatal Error[Pe1696]:cannot open source file “sys.h”
  3. Linux学习之ARM开发板连接ubuntu18.04LTS及NFS相关配置
  4. tensorrt基础知识+torch版lenet转c++ trt
  5. 用户权限管理——DB设计篇
  6. java get set 注解_java技能提升,用Lombok甩掉get和set,让代码变得更简洁
  7. C++学习之路 | PTA乙级—— 1036 跟奥巴马一起编程 (15 分)(精简)
  8. 二叉堆时间复杂度 php,二叉堆(Binary Heap)
  9. 安装服务器系统多少钱,服务器系统安装费用
  10. java 3位小数_数字有效小数第三位四舍五入