Typescript是Javascript的超集,包含Javascript所有内容,新增了类型注解
bashnpm init -y # 初始化node
npm i typescript -g # 全局安装typescript
tsc -v # 查看版本号
bashtsc -init # 初始化ts
bashtsc -w
bashnode index.js
bashnpm i ts-node -g npm i @types/node -D
bashts-node index.ts # 直接调试输出
在js的基础上,添加:
和类型即可定义变量
tslet str: string = 'ts-string'
let num: number = 123
let b1: boolean = true
let n: null = null
let b: underfined = underfined
let v: void = underfined
使用string
注解
tslet a: string = '123'
// 使用es6字符串模板
let str: string = `string${a}`
支持十六进制、十进制、八进制和二进制
tslet notANumber: number = NaN;//Nan
let num: number = 123;//普通数字
let infinityNumber: number = Infinity;//无穷大
let decimal: number = 6;//十进制
let hex: number = 0xf00d;//十六进制
let binary: number = 0b1010;//二进制
let octal: number = 0o744;//八进制s
tslet b: boolean = true
注意
Boolean
创建的对象不是布尔值tslet createBoolean: boolean = new Boolean(1) // 报错,返回的是一个Boolean对象
tslet createdBoolean: Boolean = new Boolean(1)
JavaScript 没有空值(Void)的概念,在 TypeScript 中,可以用 void
表示没有任何返回值的函数
tsfunction voidFn(): void {
console.log('test void')
}
void
类型的用法,主要是用在我们不希望调用者关心函数返回值的情况下,比如通常的异步回调函数
void也可以定义undefined 和 null类型
tslet u: void = undefined
let n: void = null;
tslet u: undefined = undefined;//定义undefined
let n: null = null;//定义null
void
与underfined
和null
的区别
void
的区别是,undefined
和 null
是所有类型的子类型。也就是说 undefined
类型的变量,可以赋值给 string 类型的变量:ts//这样写会报错 void类型不可以分给其他类型
let test: void = undefined
let num2: string = "1"
num2 = test
ts//这样是没问题的
let test: null = null
let num2: string = "1"
num2 = test
//或者这样的
let test: undefined = undefined
let num2: string = "1"
num2 = test
如果你在tsconfig.json
开启了严格模式
ts{
"compilerOptions":{
"strict": true
}
}
null
不能赋予void
类型
Any
类型
any
进行任何操作,不需要检查类型tslet anys:any = 123
anys = '123'
anys = true
any
tslet anys;
anys = '123'
anys = true
any
就失去了TS类型检测的作用unknown
类型
unknown
类型也被认为是 top type,但它更安全。与any
一样,所有类型都可以分配给unknown
ts//unknown 可以定义任何类型的值
let value: unknown;
value = true; // OK
value = 42; // OK
value = "Hello World"; // OK
value = []; // OK
value = {}; // OK
value = null; // OK
value = undefined; // OK
value = Symbol("type"); // OK
unknown
类型比any
更加严格当你要使用any
的时候可以尝试使用unknown
unknown
可赋值对象只有unknown
和any
ts//这样写会报错unknow类型不能作为子类型只能作为父类型 any可以作为父类型和子类型
//unknown类型不能赋值给其他类型
let names:unknown = '123'
let names2:string = names
//这样就没问题 any类型是可以的
let names:any = '123'
let names2:string = names
//unknown可赋值对象只有unknown 和 any
let bbb:unknown = '123'
let aaa:any= '456'
aaa = bbb
Any
类型可以调用对象的属性和方法,而unknown
不行unknown
类型更加安全ts// 如果是any类型在对象没有这个属性的时候还在获取是不会报错的
let obj:any = {b:1}
obj.a
// 如果是unknow 是不能调用属性和方法
let obj:unknown = {b:1,ccc:():number=>213}
obj.b
obj.ccc()
Object和object
Object
,可以说都是由Object
继承而来,Object
还可以写成{}
tslet a:Object = 123
let a:Object = '124'
let a:Object = []
let a:Object = () => {}
object
是除了原始类型以外的类型tslet a:Object = 123 // 错误
let a:Object = '124' // 错误
let a:Object = [] // 正确
let a:Object = () => {} // 正确
[]
类型tslet arr:boolean[] = [true,false]
tslet arr:Array<boolean> = [true,false]
tsinterface NumberArray {
[index: number]: number;
}
let fibonacci: NumberArray = [1,1,2,3,5]
tslet data: number[][] = [[1,2],[2,3]]
tsfunction Arr(...args:any): void {
console.log(arguments)
//错误的arguments 是类数组不能这样定义
let arr:number[] = arguments
}
Arr(111, 222, 333)
function Arr(...args:any): void {
console.log(arguments)
//ts内置对象IArguments 定义
let arr:IArguments = arguments
}
Arr(111, 222, 333)
//其中 IArguments 是 TypeScript 中定义好了的类型,它实际上就是:
interface IArguments {
[index: number]: any;
length: number;
callee: Function;
}
ts//注意,参数不能多传,也不能少传 必须按照约定的类型来
const fn = (name: string, age:number): string => {
return name + age
}
fn('张三',18)
ts//通过?表示该参数为可选参数
const fn = (name: string, age?:number): string => {
return name + age
}
fn('张三')
tsconst fn = (name: string = "我是默认值"): string => {
return name
}
fn()
ts//定义参数 num 和 num2 :后面定义返回值的类型
interface Add {
(num: number, num2: number): number
}
const fn: Add = (num: number, num2: number): number => {
return num + num2
}
fn(5, 5)
interface User{
name: string;
age: number;
}
function getUserInfo(user: User): User {
return user
}
this
类型tsinterface Obj {
user; number[]
add: (this:Obj,num:number)=>void
}
let obj:Obj = {
user: [1,2,3]
// 在js中无法使用
add(this:Obj,num:number) {
this.user.push(num)
}
}
obj.add(4)
tslet user:number[] = [1,2,3]
function findNum(add:number[]):number[]//如果传的是一个number类型数组就做添加
function findNum(id:number):number[]//如果传入了id就是单个查询
function findNum():number[]//如果没有传入就是查询全部
function findNum(ids?:number | number[]):number[] {
if(typeof ids == 'number') {
return user.filter(v=>v == ids)
}
else if(Array.isArray(ids)){
user.push(...ids)
return user
}else {
return user
}
}
tslet phone:number | string = 133666666 // 或者 '010-555555'
// 将接口传入的number或boolean类型转为boolean类型
let fn = function(type:number | boolean):boolean {
return !!type
}
let result = fn(0) // false
console.log(result)
tsinterface Person {
name: string
age: number
}
interface Man{
sex:string
}
const person = (man:Person & Man) => {
console.log(man);
}
person({
name: 'zhangsan',
age: 18,
sex: 'man'
})
ts// ECMAScript内置对象
let num:Number = new Number(1)
let date:Date = new Date()
let reg:RegExp = new RegExp(/\w/)
let error:Error = new Error('error')
let xhr:XMLHttpRequest = new XMLHttpRequest()
ts// DOM和BOM对象
let body: HTMLElement = document.body;
let allDiv: NodeList = document.querySelectorAll('div');
//读取div 这种需要类型断言 或者加个判断应为读不到返回null
let div:HTMLElement = document.querySelector('div') as HTMLDivElement
document.addEventListener('click', function (e: MouseEvent) {
})
tsfunction promise():Promise<number>{
return new Promise<number>((resolve,reject)=>{
resolve(1)
})
}
promise().then(res=>{
console.log(res)
})
html<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="./index.js"></script>
</body>
</html>
tslet canvas = document.querySelector('#canvas') as HTMLCanvasElement
let ctx = canvas.getContext('2d') as CanvasRenderingContext2D
canvas.height = screen.availHeight; //可视区域的高度
canvas.width = screen.availWidth; //可视区域的宽度
let str: string[] = 'XMZS%*&&979-089)()XMZ348*%%435SBXMZ*^56872&(*678ZSWSSB'.split('')
let Arr = Array(Math.ceil(canvas.width / 10)).fill(0) //获取宽度例如1920 / 10 192
// console.log(Arr);
const rain = () => {
ctx.fillStyle = 'rgba(0,0,0,0.05)'//填充背景颜色
ctx.fillRect(0, 0, canvas.width, canvas.height) // 覆盖屏幕矩形,用于清除屏幕
ctx.fillStyle = "#0f0"; //文字颜色
Arr.forEach((item, index) => {
ctx.fillText(str[ Math.floor(Math.random() * str.length) ], index * 10, item + 10)
Arr[index] = item >= canvas.height || item > 10000 * Math.random() ? 0 : item + 10; //添加随机数让字符随机出现不至于那么平整
})
// console.log(Arr);
}
setInterval(rain, 40)
interface
可以用来约束对象,定义的对象属性必须与接口一致
tsinterface Axxs{
name:string
age:number
}
let a:Axxs = {
name: 'zhangsan',
age: 18
}
tsinterface Axxs{
name:string
age:number
}
interface Axxs{
Ikun:string
}
let a:Axxs = {
name: 'zhangsan',
age: 18,
Ikun:ikun
}
ts//在这个例子当中我们看到接口中并没有定义C但是并没有报错
//应为我们定义了[propName: string]: any;
//允许添加新的任意属性
interface Person {
b?:string,
a:string,
[propName: string]: any;
}
const person:Person = {
a:"213",
c:"123"
}
注意
tsinterface Person {
name?: string
age?: number
}
ts//
interface Axxsxs{
name: string
age: number
readonly id: number
readonly cd: ()=>{}boolean
}
let a:Axxsxs = {
id: 1,
name: 'zhangsan',
age: 18,
cd: ()=> {return false}
}
a.cd = () => {return ture} //错误,函数是只读的
tsinterface Axxsxs extend Bxx{
name: string
age: number
readonly id: number
readonly cd: ()=>{}boolean
}
interface Bxx{
xxx: string
}
类型别名(自定义类型):
使用场景:
tstype CustomArray = (number | string)[]
let arr1: CustonArray = [1,'a',3,'b']
interface(接口)和type(类型别名)的对比:
在TS中,某些没有明确指出类型的地方,TS的类型推论机制会帮助提供类型。换句话说:由于类型推论的存在,这些地方,类型注解可以省略不写!
发生类型推论的2种常见场景:
有时候你会比TS更加明确一个值的类型,此时,可以使用类型断言来指定更具体的类型。
jsconst aLink: HTMLAnchorElement
const aLink = document.getElementById('link') as HTMLAnchorElement
解释:
tslet str1 = 'Hello TS'
const str2 = 'Hello TS'
此处的 'Hello TS',就是一个字面量类型。也就是说某个特定的字符串也可以作为 TS 中的类型。 除字符串外,任意的 JS 字面量(比如,对象、数字等)都可以作为类型使用
使用模式:
使用场景:
比如,在贪吃蛇游戏中,游戏的方向的可选值只能是上、下、左、右中的任意一个。
tsfunction changeDirection(direction: 'up' | 'down' | 'left' | 'right') {
console.log(direction)
}
枚举的功能类似于字面量类型+联合类型组合的功能,也可以表示一组明确的可选值。
枚举:
tsenum Direction { Up,Down,Left,Right }
function changeDirection(direction: Direction) {
console.log(direction)
}
访问枚举成员
tsenum Direction { Up,Down,Left,Right}
function changeDirection(direction: Direction) {
console.log(direction)
}
changeDirection(Direction.Up)
枚举的值
字符串枚举:
tsenum Direction {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT'
}
枚举的特点
说明︰
一般情况下,推荐使用字面量类型+联合类型组合的方式,因为相比枚举,这种方式更加直观、简洁、高效。
值的类型为 any 时,可以对该值进行任意操作,并且不会有代码提示。
tslet obj: any = {x: 0}
obj.bar = 100
obj()
const n: number = obj
尽可能的避免使用 any 类型,除非临时使用 any 来“避免”书写很长、很复杂的类型
TS 也提供了 typeof 操作符:可以在类型上下文中引用变量或属性的类型(类型查询)。
使用场景:
tslet p = {x: 1, y: 2}
function formatPoint(point: {x: number; y: number}) {}
formatPoint(p)
tsfunction formatPoint(point: typeof p) {}
TypeScript 全面支持 ES2015 中引入的 class 关键字,并为其添加了类型注解和其他语法(比如,可见性修饰符等)
实例属性初始化:
tsclass Person {
age: number
gender = '男'
}
构造函数
tsclass Person {
age: number
gender: string
constructor(age: number, gender: string) {
this.age = age
this.gender = gender
}
}
类继承的两种方式:
说明:JS 中只有 extends,而 implements 是 TS 提供的
extends
tsclass Animal {
move() { console.log( ' Moving along ! ') }
}
class Dog extends Animal {
bark( { console.log('汪! ')} )
}
const dog = new Dog()
implements
tsinterface Singable {
sing(): void
}
class Person implements Singable {
sing() {
console.log( '你是我的小呀小苹果儿')
}
}
readonly(只读修饰符)
tsclass Person {
readonly age: number = 18
constructor(age: number) {
this.age = age
}
}
两种类型系统:
TS 采用的是结构化类型系统,也叫做 duck typing(鸭子类型),类型检查关注的是值所具有的形状。 也就是说,在结构类型系统中,如果两个对象具有相同的形状,则认为它们属于同一类型。
tsclass Point { x: number; y: number }
class Point2D { x: number; y: number }
const p: Point = new Point2D()
除了 class 之外,TS 中的其他类型也存在相互兼容的情况,包括:
泛型
创建泛型函数
tsfunction id<Type>(valueL Type): Type (return value)
调用泛型函数
tsconst num = id<number>(10)
const str = id<string>('a')
简化调用泛型函数
tslet num = id(10)
泛型约束:
比如,id('a') 调用函数时获取参数的长度
tsfunction id<Type>(value: Type): Type {
console.log(value.length)
return value
}
Type 可以代表任意类型,无法保证一定存在 length 属性,比如 number 类型就没有 length。 此时,就需要为泛型添加约束来收缩类型(缩窄类型取值范围)
添加泛型约束收缩类型,主要有以下两种方式:
指定更加具体的类型
tsfunction id<Type> (value: Type[]): Type[] {
console.log(value.length)
return value
}
添加约束
tsinterface ILength { length: number }
function id<Type extends ILength>(value: Type): Type {
console.log(value.length)
return value
}
泛型的类型变量可以有多个,并且类型变量之间还可以约束
(比如,第二个类型变量受第一个类型变量约束)。
比如,创建一个函数来获取对象中属性的值
tsfunction getProp<Type, Key extends keyof Type>(obj: Type, key: Key){
return obj[key]
}
let person = { name: 'jack' , age: 18 }
getProp(person, 'name')
泛型接口:
IdFunc<number>
)。Partial<Type>
Readonly<Type>
Pick<Type, Keys>
Record<Keys, Type>
Partial<Type>
用来构造(创建)一个类型,将 Type 的所有属性设置为可选
tsinterface Props {
id: string
children: number[]
}
type PartialProps = Partial<Props>
构造出来的新类型 PartialProps 结构和 Props 相同,但所有属性都变为可选的
Readonly<Type>
用来构造一个类型,将 Type 的所有属性都设置为 readonly(只读)。
tsinterface Props {
id: string
children: number[]
}
type ReadonlyProps = Readonly<Props>
Pick<Type, Keys>
从 Type 中选择一组属性来构造新类型。
tsinterface Props {
id: string
title: string
children: number[]
}
type PickProps = Pick<Props, 'id' | 'title'>
Record<Keys, Type
构造一个对象类型,属性键为 Keys,属性类型为 Type
tstype RecordObj = Record<'a' | 'b' | 'c', string[]>
let obj: RecordObj = {
a: ['1'],
b: ['2'],
c: ['3']
}
使用场景:
tsinterface AnyObject {
[Key: string]: number
}
let obj: AnyObject = {
a: 1,
b: 2
}
在 JS 中数组是一类特殊的对象,特殊在数组的键(索引)是数值类型。 并且,数组也可以出现任意多个元素。所以,在数组对应的泛型接口中,也用到了索引签名类型
tsinterface MyArray<T> {
[n: number]: T
}
let arr: MyArray<number> = [1,3,5]
映射类型:
比如,类型 PropKeys 有 x/y/z,另一个类型 Type1 中也有 x/y/z,并且 Type1 中 x/y/z 的类型相同
这个
tstype Type = { x: number; y: number; z: number }
可以写成
tstype PropsKeys = 'x' | 'y' | 'z'
type Type = {[key in PropKeys]: number}
TS 中有两种文件类型:
.ts 文件:
.d.ts 文件:
总结:.ts 是 implementation(代码实现文件);.d.ts 是 declaration(类型声明文件)。
使用已有的类型声明文件
tsconfig.json 指定
选项
除了在 tsconfig.json 文件中使用编译配置外,还可以通过命令行来使用。 使用演示:tsc hello.ts --target es6。
注意:
本文作者:peepdd864
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!