大家好,欢迎来到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的高级类型
相对于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) }
泛型是可以在保证类型安全前提下,让函数等与多种类型一起工作,从而 实现复用,常用于:函数,接口,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