文章目录
一 环境配置
安装命令
npm install typescript -g
查看版本
tsc --version
运行ts代码(简化版)
-
webpack
-
ts-node库
- 安装ts-node
npm install ts-node -g
- 安装ts-node需要依赖tslib和@types/node两个包
npm install tslib @types/node -g
- 运行ts代码(在终端输入)
ts-node 名称.ts
二 变量声明
声明格式
var/let/const 标识符:数据类型 = 赋值
变量的类型推导
声明一个标识符时,如果直接进行赋值,会根据赋值类型推导出标识符的类型注解
- 基本数据
-
let进行类型推导,推导出来的是通用类型。
-
const进行类型推导,是字面量类型。
- 函数类型
- 参数:要明确指定参数类型,否则推导出来的是any
- 明确指定参数类型的同时也明确指定了参数的个数
function sum(num1: number,num2: number){
return num1+num2
}
- 返回值
- 可以类型推导
- 也可以明确指定
function sum(num1: number,num2: number): number{
return num1+num2
}
- 匿名函数
- 该函数参数一般会自动指定类型,不需要手动指定类型
三 数据类型
ts是js的一个超集
number
-
和js一样,不区分整数类型和浮点数类型,统一为number
-
ts也支持二进制(0b···)、八进制(0o···)、十六进制(0x···)
boolean
- 同js
string
- “” / ‘’
- 模板字符串拼接变量和字符串
let name = "kobe"
let myName = `my name is ${name}`
console.log(myName) //my name is kobe
Array
-
可以推导类型注解
-
也可以指定<数组>的类型注解:
- T[]:数组类型,并且数组中存放的T类型
- Array[T]:数组类型,并且数组中存放的T类型
Object
用于描述一个对象
- 基本使用
- 推导类型注解
-
指定类型注解
-
type IndoType = { name:string age:number } let info: InfoType = { name: "kobe", age: 18 }
-
let info : { name:string age:number } = { name: "kobe", age: 18 }
-
- 函数中接受的参数是一个对象
- 可以使用对象类型
//在对象中我们可以添加属性,并且告知ts该属性需要是什么类型
//每个属性的类型部分也是可选的,如果不指定,那么就是any类型
type PointType = {
x: number,
y: number
z?: number
}
function printCoordinate(point: PointType){
console.log("x坐标:", point.x)
console.log("y坐标:", point.y)
}
printCoordinate({x: 10,y: 30})
- 可选类型
对象类型也可以指定那些属性是可选的,可以再属性后面添加一个?
Symbol
- ES5中,不可以在对象中添加相同的属性名,例如:
const person = {
name: "kobe",
name: "jack"
}
- ES6中,可以通过symbol定义相同的属性名,因为Symbol函数返回的是不同的值,例如:
const s1: symbol = Symbol("title")
const s2: symbol = Symbol("title")
const person = {
[s1]: "kobe",
[s2]: "jack"
}
null和undefined
- 它们各自的类型也是null和undefined,意味着它们既是实际的值,也是自己的类型
let n: null = null
let n: undefined = undefined
any
在某些情况下,我们确实无法确定一个变量的类型,并且可能它会发生一些变化,这个时候我们可以使用any类型。
如果对于某些情况的处理过于繁琐不希望添加规定的类型注解,或者在引入一些第三方库时,缺失了类型注解,这个时候我们可 以使用any:
- 可以对any类型的变量进行任何的操作,包括获取不存在的属性、方法;
- 可以给一个any类型的变量赋值任何的值,比如数字、字符串的值;
let a: any = "kobe";
//a可以赋值为number类型
a = 123;
//a可以赋值为boolean类型
a = true;
//数组类型,数组中可以存放各种类型数据
const infos: any[] = ["jack", 18, {}, []]
unknown
unknown是TypeScript中比较特殊的一种类型,它用于描述类型不确定的变量。
- 和any类型有点类似,但是unknown类型的值上做任何事情都是不合法的。
- 要求必须进行类型的校验(缩小),才能根据缩小后的类型,进行对应的操作
let name: unknown = "kobe"
name = 123 //可以执行
name = "jack" //可以执行
//报错,因为name类型是unknown,无法确定name是什么类型,也就无法使用任何操作
console.log(name.length)
//类型缩小后
if(typeof name === "string"){
console.log(name.length) //可以执行
}
void
void通常用来指定一个函数是没有返回值的,那么它的返回值就是void类型。
function sum(num1: number,num2: number) {
console.log(num1+num2)
}
- 这个函数我们没有写任何类型,那么它默认返回值的类型就是void的,我们也可以显示的来指定返回值是void:
function sum(num1: number,num2: number): void {
console.log(num1+num2)
}
注意:我们可以将undefined赋值给void类型,也就是函数可以返回undefined
- 应用场景
//定义要求传入的函数类型
type ExecFnType = (...args: any[]) => void
//定义一个函数,并且接受的参数也是一个函数,而且这个函数类型必须是ExecFnType
function delayExecFn(fn: ExecFnType){
setTimeout(() => {
fn("kobe", 18)
}, 1000);
}
//执行delayExecFn函数,并且传入一个匿名函数
delayExecFn((name, age) => {
console.log(name,age)
})
/*
*1.ExecFnType类型是一个没有返回值的函数,参数是一个数组类型,且可以存放不同类型的数据
*2.函数delayExecFn,参数是一个函数,且类型是ExecFnType类型
*3.调用delayExecFn函数,参数是一个匿名函数(name,age)=> {console.log(name,age)},即:fn:(name,age)=> {console.log(name,age)}
*4.1s后,调用fn("kobe",18),fn:(name,age)=> {console.log(name,age)},所以输出kobe,18
*/
never
never 表示永远不会发生值的类型。
- 例如一个函数中是一个死循环或者抛出一个异常,那么这个函数不会返回东西,那么写void类型或者其他类型作为返回值类型都不合适,我们就可以使用never类型;
function foo(){
return []
}
- 封装框架/工具库的时候可以使用never:
function hanldMessage(message: string | number){
switch(typeof message){
case "string": console.log(message);break;
case "number": console.log(message);break;
default: const check: never = message;
}
}
//以下情况不会报错
hanldMessage("abc")
hanldMessage(123)
//报错:因为message没有指定布尔类型
hanldMessage(true)
//此时发现问题并且增加一个case:
case "boolean": console.log(message);break;
//问题解决
tuple
tuple是元组类型
- 元组数据结构中可以存放不同的数据类型,取出来的item也是有明确的类型
const infos: [string, number, number] = ["kobe", 18, 1.89]
const item = infos[0] //一定是string类型
四 联合类型和交叉类型
TypeScript的类型系统允许我们使用多种运算符,从现有类型中构建新类型。
联合类型
- 联合类型是由两个或者多个其他类型组成的类型;
- 表示可以是这些类型中的任何一个值;
- 联合类型中的每一个类型被称之为联合成员(union’s members);
- 基本使用
let foo: number | string = "abc"
foo = 123 //不会报错
//使用时要注意使用缩小联合,推断出更加具体的类型
if(typeof foo === "string"){
console.log(foo.length)
}
类型别名
我们通过在类型注解中编写 对象类型 和 联合类型,但是当我们想要多次在其他地方使用时,就要编写多次。这时我们可以给对象类型起一个别名。ty
function printId(id: number | string){
console.log("id:",id)
}
//等价于
type ID = number | string
function printId(id: ID){
console.log("id:",id)
}
接口的声明
对象的声明方式:
- 通过type:
- 通过接口:
别名和接口区别
- 区别:
- type使用范围更广,接口类型只能用来声明对象
- type不允许两个相同名称的别名同时存在;接口可以多次声明
- 接口支持继承
- 接口可以被类实现
- 类型别名和接口非常相似,在定义对象类型时,大部分时候,你可以任意选择使用。
- 接口(interface)的几乎所有特性都可以在 type 中使用;
- 总结:非对象使用type,对象使用interface
接口的特性(待写)
交叉类型
交叉类似表示需要满足多个类型的条件;交叉类型使用 & 符号;
- 应用场景(在开发中,我们进行交叉时,通常是对对象类型进行交叉的)
interface stu {
name: string,
age: number
}
interface coder {
name: string,
coding: () => void
}
const info: stu & coder {
name: "jack",
age: 18,
coding: function(){
console.log("hello")
}
}
类型断言as
有时候TypeScript无法获取具体的类型信息,这个我们需要使用类型断言(Type Assertions)。
- 比如我们通过 document.getElementById,TypeScript只知道该函数会返回 HTMLElement ,但并不知道它具体的类型:
- 规则:TypeScript只允许类型断言转换为 更具体 或者 不太具体 的类型版本,此规则可防止不可能的强制转换。
非空类型断言!
我们确定传入的参数是有值的,这个时候我们可以使用非空类型断言:非空断言使用的是 ! ,表示可以确定某个标识符是有值的,跳过ts在编译阶段对它的检测;
字面量类型
- 基本使用
const name: "kobe" = "kobe"
let age: 18 =18
- 应用场景(将多个字面量类型联合起来)
type Direction = "left" | "right" | "up" | "down"
const d: Direction = "left" //正确
const d: Direction = "jack" //错误
类型缩小
-
我们可以通过类似于 typeof padding === “number” 的判断语句,来改变TypeScript的执行路径;
-
在给定的执行路径中,我们可以缩小比声明时更小的类型,这个过程称之为 缩小( Narrowing );
-
而我们编写的 typeof padding === "number 可以称之为 类型保护(type guards);
-
类型保护:
- typeof
- ===
- !==
- instanceof
JavaScript 有一个运算符instanceof,来检查一个值是否是另一个值的“实例”:
- in等等
Javascript 有一个in运算符,用于确定对象是否具有带名称的属性.
如果指定的属性在指定的对象或其原型链中,则in 运算符返回true;
平等缩小
我们可以使用Switch或者相等的一些运算符来表达相等性:比如
- ===
- ==
- !==
- and !=