TS简单介绍以及用法

TS简单介绍以及用法TS 是 TypeScript 的缩写 是 JavaScript 的超集 JS 有的 TS 都有 也可以说 TS 是 type js 加了一个类型

大家好,欢迎来到IT知识分享网。

TS简单介绍以及用法

一、什么是TS

TS是TypeScript的缩写,是JavaScript的超集 (JS有的TS都有),也可以说TS是 type + js,加了一个类型。比如:JS:let a = 0,TS:let a:number=0

为什么需要给JS添加type呢?因为js的类型系统存在“先天缺陷”,JS代码中绝大部分的错误都是类型错误,那么就会存在一个问题,那就是找bug、改bug的时间增加,严重影响了开发效率。

从编程语言的动静来区分;TS属于静态类型的编程语言,JS属于动态的编程语言。

  • 动态编程语言:执行期间做类型检查
  • 静态编程语言:编译期间做类型检查

TS相对于JS的优势:

  • 更早发现代码中的错误,减少找bug、改bug的时间,提升了程序员开发效率。
  • 程序中任何位置的代码 都有 代码提示, 知道参数的类型是哪些,增加了开发体验。
  • 强大的 类型系统 提升了代码的可维护性,使得重构代码更加容易。
  • 支持最新的ECMAscript语法,体验最新的语法,让你走在前端开发的前沿。
  • TS类型推断机制,不需要你在代码中的每一个地方都添加类型标注,降低了开发成本。

二、TS的常用类型

  • 原始类型:number、string、boolean、null、undefined、symbol
  • 数组类型:两种写法:1、number[] 2、Array< number > 定义两个:(number|string)[]
  • 对象类型:1、需要申明对象中的属性,例如:let obj :(name:string;age:number;sayWorld(a:string):void)= {name:'你好',age:22,sayWorld(a){}},
    2、可选参数和下面函数写法一致
  • 类型别名:type 如下:
type stateArray = ( number | string )[] let a: stateArray =[1,2,'a'] let b: stateArray =[3,4,'a',5] 
  • 函数类型:1、单独制定参数、返回值类型 , 2、同时指定参数和返回值的类型
    特殊的函数类型 void (表示没有返回值)
    可选参数 在参数后面加一个问号 可选参数只能放在必选参数后面

//1、单独制定参数、返回值类型 function fn(num1:number,num2:number):number{ 
    retuen num1+num2 } const fun = (num1:number,num2:number):number=>{ 
    retuen num1+num2 } //2、同时指定参数和返回值的类型 const fun1:(num1:number,num2:number)=>number = (num1,num2)=>{ 
    reurn num1+num2 } //可选参数 没有返回值 const fun = (num1:number,num2?:number):void=>{ 
    } 
  • 接口 interface关键词
interface state { 
    name:string; age:number; sayHi():void number?:number; } let obj:state ={ 
    name:'你好', age:'22', sayHi(){ 
   }, } 
  • 接口 extends 关键字 例如:
interface state2D{ 
   x: number; y: number} interface state3D extends state2D{ 
   z:number} let d3: state3D ={ 
    x:1, y:2, z=3 } 
  • 元组类型

元组类型是另一种类型的数组,他知道数组中到底有多少个元素,以及特定索引对应的类型let array:[number,number]=[1,2]

  • 类型推论
//1\声明变量并初始化的时候  let num = 10 //number类型 let str = 'string'//string类型 num = '10'//报错 //2、决定函数返回值 function add(num1:number,num:number){ 
    //类型推断是 number return num1 + num2 } 

到这里,又有人迷糊了,这不是和js是一样的吗?其实还是不一样的,在ts中 变量声明并且马上给初始值时。ts的类型推断会自动加上,在后面就不能赋值其他类型,否则会报错,js则不会

  • 类型断言 as

有时候你会比TS更加明确一个值的类型,此时,可以使用 类型断言 来指定更具体的类型。比如:

//html <a herf="http://baidu.com" id="linl">百度</a> //TS const aLink = document.getElementById('link) //aLink : HTMLElement //此时 aLink是HTMLElement 类型,只有一些基本的属性,访问不到 a标签的herf等属性 // 此时我们需要用类型断言来解决这个问题 const aLink = document.getElementById('link) as HTMLAnchorElement //使用 as 关键字实现类型断言 //关键字 as 后面的类型是一个更加具体的类型 (HTMLAnchorElement 是 HTMLElement 的一个子类型) //通过类型断言,aLink的类型变得更加具体,这样可以访问a标签的特有属性和方法了 //另一种写法 const aLinl = <HTMLAnchorElement>document.getElementById('link') //react中用不了 冲突 

到这里就有人会问了,我怎么知道这些到底 具体是什么元素呢 这时候我们就可以利用浏览器打印来知道具体的类型,在审查元素选中标签, console.dir($0) 打印,saajbv点击打开 滑倒最下面可以看到了,英语比较好的 直接写就好了。

  • 字面量类型
    不同的声明方式,在TS中会有不同的数据类型,比如:
let str1 = 'Hello TS' //String 数据类型 const str2 = 'Hello TS' // Hello TS 数据类型 

这是为什么呢?因为 let声明的是一个变量,可以更改值,所以类型为:string . 而const声明的是一个常量,不能更改值,值只能是Hello TS,所以TS默认他的数据类型是Hello TS

使用场景:用来表示一组明确的可选值列表,比如需要声明一个函数,参数只能是 上下左右

function fun (direction:'up'|'down'|'left'|'right'){ 
    } fun('up') //此时 fun函数只能接收 up down left right 四个参数 否则报错 
  • 枚举类型
enmu Direction { 
    Up,Down,Left,Right} //逗号分隔,不是| 枚举值以大写字母开头 function fun (direction :Direction){ 
    } //形参direction 的类型为枚举Direction,那么实参的值就应该是Direction 中成员的任意一个。 //枚举成员是有值的,是从0开始的自增数 Up:0 Down:1 Left:2 Right:3 // 当然,也可以也可以给枚举中的成员初始化值。 enmu Direction { Up=2,Down=4,Left=6,Right=8} fun(Direction .Up) //如果enmu Direction { Up=2,Down,Left,Right} 那么 Down:3 以此类推 //访问枚举成员直接使用点(.)语法。类似js中的对象. 

当然,枚举成员的值也可以是字符串,如果是字符串的话 那么枚举所有成员的初始值都需要被定义,因为字符串没有自增长行为。

  • any类型 (不推荐使用)

这会让 ‘TypeScript’变成 ‘AnyScript’ (失去TS的类型保护的优势),因为当值的类型是any时,可以对该值进行任意操作,并且不会有代码提示,
具有隐式 any 类型的情况:声明变量不提供类型也不提供默认值,函数参数不加类型

  • typeof 操作符

众所周知,在js中 typeOf 是用来获取数据类型的,实际上,TS也提供了 typeOf 操作符:可以在类型上下文中引用变量或属性的类型(类型查询)。当然在TS中也可以使用JS中的用法。两者区别如下:

let p = { 
    a: 1, b: 2, } //js console.log(typeof p) //打印 'object' //TS function fun(point:{ 
    a:number,b:number}){ 
   } fun(p) //可以用typeof 进行优化 function fun (point: typeof p){ 
   } fun(p) //当然 也可也获取对象中的类型 let c:typeof p.a //c的类型就是number 

三、TS的高级类型

  • class类

相对于JS中class类,在TS中添加了几种方法: implements(实现接口)、可见性修饰符:pubilc(公有的),protected(受保护的),private(私有的),readonly(只读)。

1、JS里的使用
//JS中的基本使用 class Person{ 
    name: string //没有默认值的 需要添加类型 如果没有添加 会默认为 any  //age = 18 //如果有默认值,不需要添加类型,有类型推断 会自动默认为number // age:number = 18 //这样写也是可以的 不过我们能省则省 age :number //构造函数 constructor(name:string,age:number){ 
    this.name = name this.age = age } //实例方法 AddAge(n:number){ 
    this.age +=n } } const p = new Person('张三',18) //实例对象 P 的类型就是 Person p.AddAge(2) console.log(p)// Person { name: '张三', age: 20 } 用 . 可以访 具体属性' // 继承 extends  class Son extends Person{ 
    rideAge(n:number){ 
    this.age *=n } } const s = new Son('李四',18) console.log(s.name) //李四 console.log(s.age) //18 s.AddAge(1) console.log(s.age) //19 s.rideAge(2) console.log(s.age) //38 
2、 implements(实现接口)
// implements interface state{ 
    sing():void } class Person implements state{ 
    sing(){ 
    console.log('唱歌') } } 
3、可见性修饰符
(1)、public(公开的)
// 默认就是 public(公开的) 写不写都可以 class Example { 
    public move(){ 
    console.log('移动了') } } 
(2)、protected(受保护的)
//protected 受保护的 只能在class本身 或者子类中使用 class Person { 
    protected move(){ 
    console.log('移动了') } } class Son extends Person{ 
    run(){ 
    this.move() // 正常 可以调用到 } } const p =new Person() p.move // 报错 属性“move”受保护,只能在类“Person”及其子类中访问 const s =new Son() s.move // 报错 属性“move”受保护,只能在类“Person”及其子类中访问 
(3)、private(私有的)
//private(私有的) 只能在当前class内部使用 class Person1 { 
    private move(){ 
    console.log('移动了') } } class Son1 extends Person1{ 
    run(){ 
    this.move() // 报错 属性“move”为私有属性,只能在类“Person1”中访问 } } const p1 =new Person1() p1.move // 报错 属性“move”为私有属性,只能在类“Person1”中访问 const s1 =new Son1() s1.move // 报错 属性“move”为私有属性,只能在类“Person1”中访问 
(4)、readonly(只读属性)
//readonly 只读属性 class Person2{ 
    //如果属性设置为 readonly 需要指定类型  // 不指定类型又有初始值时 类型会默认为初始值  // 不指定类型又没有初始值时,类型为any readonly age:number = 18 constructor(age:number){ 
    this.age = age } // 错误演示 readonly不能对方法使用 // readonly say(){} //报错"readonly" 修饰符仅可出现在属性声明或索引签名中。 } // readonly 不仅仅可以使用在class类里面 还可以在接口interface 和{}类型声明 里面使用 interface state { 
    readonly name:string } let state:state = { 
    name:'1' } state.name = '2' // 报错 无法分配到 "name" ,因为它是只读属性。 let obj:{ 
    readonly name:string} = { 
    name:'1' } obj.name = '2' // 报错 无法分配到 "name" ,因为它是只读属性。 
  • 类型兼容性

  • 交叉类型 (&

交叉类型(&):功能类似于接口继承(extends),用于组合多个类型为一个类型(常用于对象类型)

// 交叉类型 interface Person{ 
    name:string } interface Son{ 
    age:number } type SonD = Person & Son let S :SonD ={ 
    name:'张三', age:18} let S1:(Person & Son)={ 
    name:'张三', age:18} 

在这里可以看出 交叉类型和 继承好像没有什么不同,那我们来说一下两者不同的地方,如果属性或者方法又冲突的时候,两者处理的方式不一样,看下面代码

interface Person{ 
    say:(a:number)=>string } // 继承 interface Son extends Person{ 
    say:(a:string)=>string } // 报错 // 接口“Son”错误扩展接口“Person”。 // 属性“say”的类型不兼容。 // 不能将类型“(a: string) => string”分配给类型“(a: number) => number”。 // 参数“a”和“a” 的类型不兼容。 // 不能将类型“number”分配给类型“string”。 //交叉类型  interface Son1{ 
    say:(a:string)=>string } type SonD = Person & Son1 let S1:SonD ={ 
    say(value:number|string){ 
    return '' } // (property) say: ((a: number) => string) & ((a: string) => string) } 
  • 泛型和keyof

泛型是可以在保证类型安全前提下,让函数等与多种类型一起工作,从而 实现复用,常用于:函数,接口,class中。

1、泛型基本使用
function fun<Type>(val:Type):Type{ 
    return val } fun<number>(1) //function fun<number>(a: number): number fun<string>('1') //function fun<string>(val: string): string // 简化 fun(1) //function fun<1>(val: 1): 1 
2、泛型约束

两种方式代码如下:

// 1、指定更加具体的类型 比如指定数组,我们就可以访问数组中的.length属性 function fun <Type>(val:Type[]):Type[]{ 
    console.log(val.length) return val } fun<string>(["1","2"]) // 2、添加约束  interface ILength{ 
    length:number } // 只要含有length属性都可以 function fun1<Type extends ILength>(val:Type):Type{ 
    console.log(val.length) return val } fun1([1,2]) fun1('') fun1({ 
   length:50,age:18}) fun1(123) // 报错 类型“number”的参数不能赋给类型“ILength”的参数 // 泛型变量可以是多个 看下面代码  // keyof 关键字 接收一个对象类型,生成其键名称(可能是字符串或数字)的联合类型 function fun2<Type ,Key extends keyof Type>(obj:Type,key:Key){ 
    return obj[key] } // 一般情况 let person = { 
   name:'张三',age:18} fun2(person,'name') // 了解补充 fun2('asd','charAt') fun2(12,'toFixed') fun2('asd',1) 

泛型接口和泛型类

// 泛型接口 interface stateId<Type>{ 
    id:(val:Type)=>Type ids:()=>Type[] } let obj:stateId<number>={ 
    id(val){ 
    return val }, ids(){ 
    return [1,2,3] } } // 其实 数组就是一个泛型接口  let arr = [1,2,3] arr.forEach(item=>{ 
    //(method) Array<number>.forEach(callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any): void }) // 泛型类 class Person<Type>{ 
    defaultValue:Type add:(num1:Type,num2:number)=>number } let p = new Person<number>() p.defaultValue = 10 //可以省略不写 class Person1<Type>{ 
    defaultValue:Type constructor(value:Type){ 
    this.defaultValue = value } } let p1 = new Person1(10) 

泛型工具类型

// Partial< Type > 把已有的全部转换成可选属性 interface state { 
    id:number, ids:number[] } type PartialState = Partial<state> // 变换成这样 全部属性变成可选 // type PartialState = { 
    // id?: number | undefined; // ids?: number[] | undefined; // } let P:PartialState = { 
   } // Readonly< Type > interface state1 { 
    id:number, ids:number[] } type ReadonlyState1 = Readonly<state1> // 变换成这样 全部属性变成可选 // type PartialState = { 
    // id?: number | undefined; // ids?: number[] | undefined; // } let P1:ReadonlyState1 = { 
    id:1, ids:[1] } P1.id = 10 //报错 无法分配到 "id" ,因为它是只读属性。 // Pick< Type,Key > 选择一些属性来构造新的类型 interface state2 { 
    id:number, ids:number[] } type PickState2 = Pick<state2,'id'> // 变换成这样 全部属性变成可选 // type PartialState = { 
    // id?: number | undefined; // ids?: number[] | undefined; // } let P2:PickState2 = { 
    id:1, ids:[1] // 报错 不能将类型“{ id: number; ids: number[]; }”分配给类型“PickState2”。对象文字可以只指定已知属性,并且“ids”不在类型“PickState2”中。 } //Record <Keys, Type > 构建一个对象类型,属性的键为Keys,属性类型为 Type type RecordObj = Record<'a'|'b'|1,string[]> let obj:RecordObj = { 
    a:['1'], b:['1'], 1:['1'] } 
  • 索引签名类型和索引查询类型

在开发中,当无法确定对象中有哪些属性的时候,就要用到索引签名类型了。

// 对象 对象中的键值一定是字符串类型 interface state { 
    [key:string]:string } let obj:state={ 
    a:'1', b:'2', } // 在TS中 数组是一个特殊的对象 特殊在数组的键(索引)是数值类型 interface MyArray<T>{ 
    [n:number]:T } let arr:MyArray<number> = [1,2,3] 
  • 映射类型

type propsKey = 'X'|'Y'|'Z' // type1 type2 实现效果一样 type Type1 = { 
   x:number,Y:number,z:number} type Type2 = { 
   [key in propsKey]:number} // type Type2 = { 
    // X: number; // Y: number; // Z: number; // } // 基于对象 keyof 获取键值 相当于 'X'|'Y'|'Z' type propsKey2 = { 
   x:number,Y:string,z:boolean} type Type3 = { 
   [key in keyof Type1]:number} // type Type3 = { 
    // x: number; // Y: number; // z: number; // } 

索引查询(访问)类型

type a = { 
   x:number,b:string,c:boolean} type b = a['x'] //type b = number //模拟 Partial 实现 type MyPartial<T>{ 
    [p in keyof T]?:T[p] } type PartialStates = MyPartial<a> // type PartialStates = { 
    // x?: number | undefined; // b?: string | undefined; // c?: boolean | undefined; // } // --- // 同时查询多个索引的类型 type c = a['b'|'c'] //type c = string | boolean type d = a[keyof a] //type d = string | number | boolean 

感谢浏览观看 关注博主 一起学习!!!

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/134692.html

(0)
上一篇 2025-07-10 16:00
下一篇 2025-07-10 16:15

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信