TS 总结

1.TS 有什么优点和缺点?适应场景

2.TS 的数据类型有哪些?

3.TS 中 any 、void 、never、 unknwon 的区别?

4. TS 访问修饰符有哪几个?

5. # 和 private 定义的私有属性有什么区别?

6.TS中 type 和 interface有什么区别?如何选择?

7.说说你对TS中泛型的理解?

8.TS中交叉类型和联合类型是什么?

9.TS中有哪些特殊的符号?分别是什么意思?

10.TS常见的 工具类型 有哪些?

11.TS 如何扩展 window 属性?

12.TS 如何处理第三方模块的类型?

1.TS 有什么优点和缺点?适应场景

  优点

      • TS是静态类型
      • TS有类型错误检查,而且是在编译时就报错(而非运行时)
      • TS有智能提示,提高开发效率和稳定性      

       缺点

      • 有一定学习成本
      • 某些情况,类型定义过于混乱,可读性差      

       适应场景

      • 大型项目,业务复杂,维护人员多
      • 逻辑性比较强的代码,需要类型更稳固
      • 组内至少有一个懂TS 的技术leader负责来把控代码规范        

2、TS 的数据类型有哪些? 

    • boolean (布尔类型)
    • number (数字类型)
    • string (字符串类型)
    • symbol
    • undefined (未定义)  
      • 只能赋值本身和void类型  
        let c: undefined = undefined;
        c = void(0);
        c = undefined;
    • null (空值,无值) 
      • 只能复制本身
        let value:null = null;
        value = null
    • void (没有类型)
      • 配合函数使用,表示该方法没有返回值
        function hello():void{
              alert('hello')
        // 或者返回 undefined
        // return undefined }
    • any (任意类型)
      • 使用any类型时,不会做类型检查,甚至可以调用起属性和方法。和JS一样。
        let  num:any = 123
        num = '24'
        num = true
        num.a
      • 定义存储各种类型数据的数组时 
        let arrList: any[] = [1,false,'34']
        arrList[1] = 100
    • never (永远不存在的类型)
      • 一般用在总会抛出异常或者无限循环中
        复制代码
        // 死循环,无限循环
        function f(): never{
             while(true){}  
        }
        
        // 抛出异常
        // 返回 never 的函数必须存在无法到达的终点
        function err(message: string): never{
              throw new Error(message)
        }
        复制代码
    • unknown (未知类型)
      • 当不确定变量的具体类型时,可以使用unknown
      • unkwon 是安全的 any类型
      • unknwon 需要通过类型断言或类型检查才能进行操作
        let b: unknown;
        b = true;
        b = '123';
        
        console.log(b.length) // 错误
        console.log((b as string).length) //需要断言
    • array(数组类型)
      • 数组array 是单一类型的
      • 两种写法:
        • 类型后面 + []  
          let arr:string[] = ['1'];
          arr = ['2','3']
        • 使用数组泛型,Array<类型> 
          let arr:Array<number>;
          arr = [1,2] 
    • tuple (元组类型)
      • 已知元素数量和类型,各个元素的类型可以不相同
      • 赋值时,类型、位置、个数需要都要和定义的一直 
        let tupleArr:[number,string,boolean];
        tupleArr = [12,'34',true] // 0k
        tupleArr = [12,'34'] // 错误的
    • enum (枚举类型) 
      • 对JS 标准数据类型的一个补充
        enum Color {
             Red,
            Green,
            Blue
        }
        
        let c: Color = Color.Red
    • object (对象类型)
      let obj:object
      obj = {name:'',age:10}

写法:变量名后加‘:’ 加上类型 的形式

const s:sting = 'a' 
let n:number;
n = 100

 

TS 可以进行类型断言,如果变量直接赋值的情况,可以去掉类型(TS 自己会根据值去判断类型):即

const s = 'a'

3、TS 中 any 、void 、never、 unknwon 的区别?

  • any 是任意类型,不做类型检查,比较危险
  • unknown 是未知类型,和any 类似,但比any更加安全。因为unknown 会进行类型检查,使用时需要使用as断言  
  • void 是没有类型,用在一个函数的返回值,比如一个函数没有返回值,或者返回undefined  
  • never 是永远不存的类型,用在函数返回,比如死循环 或者 抛出异常错误的函数,该函数永远也无法达到终点

4、TS 中 访问修饰符有哪几个?

  • public (公共) 
    • 可以自由的访问类程序里通过public定义的属性和方法。  
  • private (私有)
    • private 定义的属性和方法,只能够在该类中的内部进行访问。继承的子类和实例对象不能访问到  
  • protected (受保护)
    • 通过protected 定义的属性和方法 ,可以在该类内部和继承的子类中访问。但不能被实例对象访问 

 

复制代码
class Parent {
  public name:string
  private friend: string = 'lili'
  protected age:number
  constructor (name: string, age: number){
    this.name = name;
    this.age = age
  }
  public hello(){

  }
  private hi(){

  }
  protected getName(){

  }
}
class Child extends Parent {
  constructor(name: string ,age: number){
    super(name,age)
  }

  getInfo(){
    console.log(child1.name) //公共的方法,可以被继承类访问
    console.log(this.hello()) //公共的方法,可以被继承类访问
    console.log(this.age)//受保护的属性,可以被继承类访问
    console.log(this.getName()) //受保护的方法,可以被继承类访问
    console.log(this.hi()) //私有方法 不能不继承类访问
    console.log(this.friend) //私有属性 不能被继承类访问

  }

}
const child1 = new Child('xioaming',20)
console.log(child1.name) //公共的方法,可以被实例对象访问
console.log(child1.hello()) //公共的方法,可以实例对象访问
console.log(child1.age)//受保护的属性,可以实例对象访问
console.log(child1.getName()) //受保护的方法,可以被实例对象访问
console.log(child1.hi()) //私有方法 不能被实例对象访问
console.log(child1.friend) //私有属性 不能被实例对象访问
复制代码

 

   TS中可以通过构造函数的参数直接定义属性:

复制代码
class Parent {
  constructor(public name:string,protected age:number, private friend = 'lili'){

  }
}

//等同于下面的代码
class Parent {
  public name:string
  private friend: string = 'lili'
  protected age:number
  constructor (name: string, age: number){
    this.name = name;
    this.age = age
  }
}
复制代码

  面向对象的三要素: 1.继承 2. 封装 (保证私有属性不被访问)3. 多态(函数重载)

5. # 和 private 定义的私有属性有什么区别

  • # 和 private 在类中都是定义私有属性
    复制代码
    class Parent {
      private name:string // 私有属性
      #age:number // 私有属性
      constructor(name:string,age:number){
        this.name = name
        this.#age = age
      }
      getInfo(){
        console.log(this.name) //获取私有属性
        console.log(this.#age) //获取私有属性
      }
    }
    复制代码
  • #定义的属性,不能再构造函数参数中定义;而private可以在构造函数参数中直接定义 
    复制代码
    class Parent {
      #age:number // 私有属性
      constructor(private name:string,age:number){
        this.#age = age
      }
      getInfo(){
        console.log(this.name)
        console.log(this.#age)
      }
    }
    复制代码
  • private定义的私有属性,只是在编译时检查会给出警告,外部代码可以通过一些编译警告来访问这些成员(eg: 通过 as any进行断言 )。但在编译后的JS代码中,这些成员实际上是公开的。
  • #定义的私有属性是真正的私有属性,只能在类的内部访问。外部代码无法访问这些成员。即使编译后的JavaScript代码仍也无法通过常规方式访问到
  • # 适用于需要严格保护类成员不被访问的场景,确保封装性和安全性
  • private 使用于在编译时进行检查,但不需要严格运行时进行隔离的场景。

6、TS中 type 和 interface有什么区别?如何选择?

  •   类型别名 type:
    • 类型别名:是用来给一个类型起个新名字的
    • type可以支持多种类型定义:包括基本类型、对象类型、联合类型、交叉类型、元组等等
      复制代码
      type Name = string
      type List = Array<number>
      //对象 type UserType ={ name: string age: number getName: ()=> string }
      // 函数
      type SetName = (name: string)=> void
      复制代码

   接口 interface:

    • 接口interface:是一种用来描述对象或函数的东西
      复制代码
      // 对象
      interface User { name: string age: number getName: ()
      => string }
      // 函数
      interface setName {
      (name:string):void
      }
      复制代码

   二者的相同点:

    • 都可以描述一个对象结构
    • 都可以被 类class来实现接口,必须使用 implements 关键字
      复制代码
      //interface 定义的类型
        interface User {
          name: string
          age: number
          getName: ()=> string
        }
        //type 定义的类型
        type UserType ={
          name: string
          age: number
          getName: ()=> string
        }
        // Person 类实现了 User 接口
      class Person implements User{
        name: string;
        age: number
        getName: () => string
      }
      // Person 类实现了 UserType 接口
      class Person implements UserType{
        name: string;
        age: number
        getName: () => string
      }
      复制代码
    • 都可以扩展属性
      • interface 扩展interface 
        复制代码
        interface User {
          name: string
          age: number
        }
        
        interface School {
          schoolName:string
          schoolDress:string
        }
        
        // User2 接口 扩展了 User 和 School
        interface User2 extends User,School{
          salary:number
        }
        
        const user: User2= {
          name: '23',
          age:20,
          schoolName:'ww',
          schoolDress:'xxxxx',
          salary: 30
        }
        复制代码
      • interface 扩展 type
        复制代码
        type User = {
          name: string
          age: number
        }
        
        //User 接口 扩展了User
        interface User2 extends User{
          salary:number
        }
        
        const user: User2= {
          name: '23',
          age:20,
          salary: 30
        }
        复制代码
      • type  扩展type
        复制代码
        type User = {
          name: string
          age: number
        }
        
        type School = {
          schoolName:string
          schoolDress:string
        }
        // User2 类型 扩展 
        // type 类型的扩展使用交叉类型(&)
        type User2 = User & School & {
          salary:number
        }
        
        const user: User2= {
          name: '23',
          age:20,
          schoolName:'x',
          schoolDress:'xxx',
          salary: 30
        }
        复制代码
      • type 扩展 interface  
        复制代码
        interface User {
          name: string
          age: number
        }
        
        type User2 = User & {
          salary:number
        }
        
        const user: User2= {
          name: '23',
          age:20,
          salary: 30
        }
        复制代码

  区 别: 

    • type 可以是基础类型、联合类型、交叉类型;interface 不可以
    • typeof  可以通过typeof复制;interface 不可以
    • interface 可以合并声明,type不可以重复定义
      复制代码
      interface User {
        name: string
      }
      
      interface User {
        age: number
      }
      
      // interface 会合并声明
      const user: User= {
        name: '23',
        age:20
      }
      复制代码
      //type 不能重复定义
      type User = {
        name:string
      }
      // 会报标识符 User 重复
      type User = {
        age:number
      }

   type 和 interface 如何选择?

    • TS的初衷:type 定义类型关系;interface 定义数据结构
    • 但实际使用时,我们很多时候模糊不清
    • 个人建议:优先使用 interface,再使用type  

7.说说你对TS中泛型的理解?  

  是什么?

    • 泛型指定义函数、类或接口时,不预先定义好具体类型,而是使用类型参数作为占位符 
    • 这些占位符在函数、类或者接口被实例化或调用时,再被指定类型        

  泛型的具体应用场景:

    • 函数
      • 简单例子:
        function fn<T>(arg: T): T{
          return arg
        }
        fn<string>('hello')
        fn<number>(100)
      • 可以一次定义多个类型参数

        function fn3<T,U>(tupe:[T,U]):[U,T]{
          return [tupe[1],tupe[0]]
        }
        fn3<number,string>([100,'23'])
        fn3<boolean,string>([true,'23'])
      • 基本使用
        复制代码
        class Person<T> {
          name:T
          constructor(name:T){
            this.name = name
          }
          getName(): T {
            return this.name
          }
        }
        new Person('xxxx')
        new Person(12)
        复制代码
      • 可以使用<T extends xx> 方式约束泛型
        复制代码
        type Params = string | number
        class Person<T extends Params> {
          name:T
          constructor(name:T){
            this.name = name
          }
          getName(): T {
            return this.name
          }
        }
        复制代码
    • 接口
      •   
        复制代码
        interface User<T,U> {
          id: T
          name: string
          age: number
          sex: U
        }
        const u: User<string,number> = {
          id: '1',
          name: '33',
          age: 24,
          sex: 0
        }
        const u2: User<string,string> = {
          id: '1',
          name: '33',
          age: 24,
          sex: '女'
        }
        复制代码

 

8.TS中交叉类型和联合类型是什么? 

  • 交叉类型
    • 通过 “&” 将多个类型合并为一个类型,即 U1 & U2&U3。可以获取所有属性
      复制代码
      interface U1 {
        name: string
        city: string
      }
      
      interface U2 {
        name: string
        age: number
      }
      
      const user1:UserType = {
       name:''",
        city:'',
        age:10
      }
      复制代码
    • 缺陷:属性类型不能冲突。如果属性类型冲突,那该冲突属性类型会被标记为never
    • 交叉类型只能合并对象类型,基础类型无法交叉,会返回never
    • 应用场景:合并多个对象的属性
  • 联合类型 
    • 联合多个类型 T1|T2|T3,一种“或”的关系
    • 联合类型可以是基础类型也可以是对象类型
      复制代码
      interface U1 {
        name: string
        city: string
      }
      interface U2 {
        name: number
        age: number
      }
      
      function fn(): U1 | U2{
        return {
          name:'',
          //name:1,
          age:10,
          city:'xx'
        }
      }
      
      type T = string | number
      复制代码

9.TS中有哪些特殊的符号?分别是什么意思? 

  • ?
    • 可选
    • 在函数中,可选参数必须放到后面。
      复制代码
      type User ={
        name: string
        age?:number //可选参数
        city:string
      }
      const u:User = {name: '',city:'ss'}
      console.log(u)
      
      //函数中的可选参数必须放到后面
      function fn(a:number,b?:string){
        console.log(a,b)
      }
      fn(12)
      复制代码
  • ?.
    • 可选链操作符。
    • 用在访问对象属性时进行安全检查,如果对象链中的任何一部分为 null或者undefined,则直接返回null或者undefined。
      // 如果 info 不存在,则直接返回undefined,而不会报错
      const city = user?.info?.city
    • 使用场景:开发者不确定对象是否为空,进行安全的属性访问,避免运行时出错 
  • ??
    • 空值合并云算符,当左侧是null或者 undefined 时会返右侧
    • 和 || 有点像,|| 是左侧为假时返回右侧
      复制代码
      const user = {
           name:'zhangsan',
          index: 0
      }
      
      const n1 = user.name ??  '暂无姓名'  // 'zhangsan'
      const n2 = user.name ||  '暂无姓名'  // 'zhangsan'
      const i1 = user.id ?? '暂无 id'  // 0
      const i2 = user.id ||  '暂无 id'   // 暂无 id
      复制代码
  • !
    • 非空断言,告诉编译器某个值就对不会是null或者 undefined
      function fn1(a?:string){
        return a!.length
      }
    • 使用场景:开发者明确某个值不会是 null或 undefined,希望TS忽略空值检查的场景  
  • _
    • 数字分隔符,用来提高代码可读性
    • 适用场景: 货币、手机等等
      const million = 1_000_000 //1000000
      const  phone = 151_1234_2345 //15112342345
  • &
    • 交叉类型  
  • |
    • 联合类型   
  • # 
    • 类中定义的私有属性     

10. TS常见的 工具类型 有哪些?

  • Partial<T>
    • 将类型T中的所有属性变为可选属性 
      复制代码
      interface User {
        name:string
        age: number
        city?:string
      }
      
      const user1: Partial<User> = {
        name:''
      }
      复制代码
  • Required<T>
    • 将类型T中的所有属性变为必选属性。相当于把可选属性全部去掉
      复制代码
      interface User {
        name:string
        age: number
        city?:string
      }
      
      const user1: Required<User> = {
        name:'',
        age:10,
        city:'北京' // city 也必选
      }
      复制代码
  • Pick<T,K>
    • 从类型T中选择一组属性。
      • K是有一个属性名或者属性名的联合类型
        复制代码
        interface User {
          name:string
          age: number
          city:string
        }
        
        // 只包含name 属性
        const user1: Pick<User,'name'> = {
          name:''
        }
        //只包含 name 和 age  属性
        const user2: Pick<User,'name' | 'age'> = {
          name:'',
          age:18
        }
        复制代码
  • Omit<T,'属性名'>
    • 从类型T中排出某些属性 
      复制代码
      interface User {
        name:string
        age: number
        city?:string
      }
      
      //去掉name 属性
      const user1: Omit<User,'name'> = {
        age:10,
        city:'' //可选的
      }
      //去掉 name 和 age  属性
      const user2: Omit<User,'name' | 'age'> = {
       city:'222' //可选的
      }
      复制代码
  • Exclude<T>
  • Extract<T>
  • Readyonly<T>  
    • 将T中的所有属性变为只读,不允许修改 
      复制代码
      interface User {
        name:string
        age: number
        city?:string
      }
      
      type User2 = Readonly<User>
      
      const user: User2 = {
        name:'',
        age:10,
        city:'北京' //可选的
      }
      
      //user.name = 'lisi' 不能不修改
      复制代码
    • 和类型属性前面加只读属性一样

      interface User {
        readonly name:string
        readonly age: number
        readonly city?:string
      }
    • const 和 readonly区别

      • const 定义的变量为只读

      • readonly 定义只读属性

11. TS如何扩展 window 属性 

    • 新建一个xx.d.ts 声明文件
    • xx.d.ts文件中 用declare 声明 Window 接口,接口中可以定义我们自己的属性
      // xx.d.ts 声明文件
      
      declare interface Window { // Window 首字母大写
        test: string
      }
    • 使用时,也不需要引入,直接用即可

      window.test = "Hello, World!";
      
      console.log(window.test); // 输出: Hello, World!

 

 12. TS 如何处理第三方模块的类型? 

    • 现在很多插件都是直接用TS开发的,本身包好了类型定义
    • 常见的第三方插件,都有‘@types/xxx’包,安装即可使用
    • 其他的,可以通过 declare moudule xxxx 定义类型 
      复制代码
      // xxx.d.ts 文件中声明
      
      declare module 'someModule' {
      // prop 是 someModule 中需要的参数 
      function fn(prop:number): void { } export {fn} }
      复制代码
    • 在使用的地方 直接import 导入函数即可使用

      import   {fn} from 'someModule'
      
      fn(200)

       

           
        

 

            

  

 

               

posted @   yangkangkang  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示