大厂面试TS(上)

一、TS面试基础知识

1、什么是TS?

  • 概念:
    ts 是 js 的超集,即在原有的js语法基础上,添加强类型并切换为基于类的面向对象语言
  • 特点

面向项目:
TS - 面向解决大型的复杂项目、架构、代码维护复杂场景
JS - 脚本化语言,用于面向简单页面场景

自主检测:
TS - 编译时,主动发现并纠正错误
JS - 运行时,执行报错

类型检测:
TS - 强类型语言,支持动态和静态的类型检测
JS - 弱类型语言,无静态类型选项

运行流程:
TS - 依赖编译,依靠编译打包实现在浏览器端的运行
JS - 可直接在浏览器端运行

复杂特性:
TS - 模块化、接口、泛型

2、安装运行

  npm install -g typescript
  tsc -v
  tsc xxx.ts

举栗: 问: 在字符串后面加上:string,代码运行时,这个string还存在吗? 有什么办法在运行时改变这个string吗?
答案: 不存在了,也没必要去修改这个string,它是在编译时为变量指定了一个类型。

3、TS 基础类型和语法

  • 类型: boolean 、string 、number 、arrary、 null 、undefined
// es
let a = false;
// ts
let a:boolean = false;
// 统一方式 & <> 方式
let classArr: string[] = ['1', '2'];
let classArr: Array<string> = ['1', '2']
  • 那如果数组中的各个元素类型不一样的话呢?
    tuple - 元祖
let tupleType:[string, boolean] = ['1', true]
  • 特定的几个值呢 ====> 也就是枚举?
   // 数字型枚举 - 默认从0开始,一次递增
  enum Store {
      BAD, // 不写默认0分
      GOOD, // 不写默认1分
      NICE=10, // 写默认10分
  }
  let score: Score = Score.BAD;
  // 字符串枚举 - 默认从0开始,一次递增
  enum Store {
      BAD = 'BAD', 
      GOOD = 'GOOD',
      NICE = 'NICE', 
  }
  // 反向映射
   enum Store {
      BAD, // 不写默认0分
      GOOD, // 不写默认1分
      NICE=10, // 写默认10分
  }
  let scoreName = Score[0] // 结果为'BAD'
  let scoreValue = Score['BAD'] // 结果0
  // 异构
  enum Enum{
    A,     // 0
    B,     // 1
    C = 'C',
    D = 'D',
    E = 8,
    F       // 9
  }
  // 面试题: 异构类型每一项的枚举值 => 进而问如何手写一个异构枚举??
  let Enum;
 (function (Enum) {
   // 正向
   Enum['A'] = 0;
   Enum['B'] = 1;
   Enum['C'] = 'C';
   Enum['D'] = 'D';
   Enum['E'] =8;
   Enum['F'] = 9;

   // 逆向
   Enum[0] = 'A';
   Enum[1] = 'B';
   Enum[8] = 'E';
   Enum[9] = 'F';

  })(Enum || Enum = {})
  • 那我想绕过所有的类型检查呢 ==> any 类型检查和编译筛查取消
   let anyValue:any = '1';
   anyValue = false;
   let value1:boolean = anyValue // OK 使用前无需判断any类型
  • 还有一个种方式是 ==> unknown 绕过赋值检查,禁止更改传递
   let unknownValue: unknown = '1';
   unknownValue = 123;
   unknownValue = false;
   let aa:unknown = unknownValue // OK 
   let bb:any = unknownValue // OK 
   let cc:boolean = unknownValue // OK
   let cc:string = unknownValue // Error  使用之前要先判断类型是否符合

上述两种方式any 和unknown 有何区别??
1、任何类型都可以是any类型,ts 允许any类型的值进行任何操作,对它一路绿灯,等于免检标签。可以访问任意属性和方法。
2、任何类型都可以是unknown类型,一旦打上标签,会被重点检查,只要类型检查通过了才能进行操作。

说人话?? 举栗如下::

// 从后台拿到数据,不知道类型,按照不同类型走不同的逻辑处理
let a:unknown = JSON.stringify({result: []})
if (typeof a === 'string'){
    let b = JSON.parse(a)
} 
// 或者 使用断言
let score:unknown = 99.8
let result = Math.round(score as number); // 这要求运行时的score必须是number才能过检查
let result1 = Math.round(<number>score); // 这是另一种写法 
  • 如何声明返回为空,没有任何类型? (告诉编辑器函数没有返回值)
// 比如没有返回值的函数
function voidFunction():void{
   console.log('void')
}
  • 永不能执行完 or 永远error (永远不会有值)
// 比如专门用来报错的函数
function errMsg(msg:string):never{
   throw new Error(msg)
}
// 或者永不会结束的函数
function infiniteLoop:never{
     while(true) {  }
}

4、接口 - interface

  • 区分开object / Object / {} - 三个不同的对象
// object - 非原始类型
interface ObjectConstructor{
    create(o:object | null):any
}
const proto = {}
Object.create(proto);
Object.create(null);
Object.create(undefined); // Error
// Object 
// Obect.prototype 上的属性保留了
interface Object {
    constructor: Function;
    toString():string;
    toLocaleString():string;
    valueOf():Object;
}
// 定义了Object 类属性
interface ObjectConstructor{
    new(value:any):Object;
    readonly property:Object;
}
// {} - 定义真正的空属性对象
const obj = {}
obj.prop = 'props'; // Error

obj.toString(); // OK
  • 对行为模块的抽象,具体的行为是由类来实现
// 描述对象内容
interface Class1 {
  // 只读
  readonly name:string;
  age: number;
}
let Wang = {
     name: 'Famous',
     age: 11
}
// 面试题 readonly  与 js 的引用操作类型不同 < = > const
let arr:number[] = [1,2,3,4]
let ro: ReadonlyArray<number> = arr;
ro[0] = 12 // ok吗? 
ro.push(5); // ok吗?
ro.length = 10; // ok吗?
arr = ro; // ok吗
// 答案是全部报错
  • 那我想要允许添加一些可能的属性呢?有些属性可能要不断增加进去
// 任意可添加属性
interface Class1 {
  readonly name:string;
  [propName:string]:any; 
}
let c1 = {name: 'JS'}
let c2 = {name: 'TS', level: 1} // level 就是后续新增的属性

5、交叉类型 - &

// 合并
interface A {
    inner: D;
}
interface B {
    inner: E;
}
interface C {
    inner: F;
}
interface D {
    d: boolean;
}
interface E {
    e: string;
}
interface F {
    f: number;
}

type ABC = A & B & C;
let abc:ABC = {
    inner:{
       d:false;
       e: 'className',
       f: 5     
   }
}
// 合并冲突
interface A {
    c:string;
    d:string;
}
interface B {
    c:number;
    d:string;
}
type AB = A & B
let ab: AB  // 此时 c 是string 也是number, 变成never 编译时会直接报错

6、断言 - 类型声明和转换(开发者和编译器做了一个告知交流)

  • 编译时作用
let anyValue:any = 'hi Lu'
// 尖括号形式
let anyLength:number = (<string>anyValue).length;
// as
let anyLength:number = (anyValue as string).length;
// 非空判断 - 只确定不是空
type A = () => number;
const start = (param: A | undefined){
  // 业务逻辑
  // if (额外判断逻辑){
      let time = param!();  // 具体类型待定,但是非空确认
   }
}
// 面试题
const tsClass:number | undefined = undefined;
const aa:number = tsClass!
console.log(tsClass) // 做好了非空判断吗?
// 上述回转义成为
const tsClass = undefined;
const aa = tsClass // undefined

// 结论 尽量不要在赋值的时候去断言

// 肯定断言 - 肯定化保证赋值
let score:number;
startClass();
console.log(score) // 使用前赋值
function startClass(){
  score = 5;
}
// 应该这样写 let score!:number; 
// 上述代码一般要在写score时就赋值,而不是等后面再赋值,但是写了断言 ,提前打好招呼,示意等下会有赋值,编辑器就不会报错了。

7、类型守卫 - 语法规范范围内,额外的确认

  • 多态 - 多钟状态(多钟类型)
// in - 定义属性场景下内容的确认(类不适合合并,走导流)
interface Teacher {
  name: string;
  courses:string[];
 }
interface Student {
  name: string;
  startTime:Date;
 }
type ClassA =  Teacher | Student
function startCourse(cls:Class){
    if ('courses' in cls){
        console.log('Courses:' + cls.courses)
    }
    if ('startTime' in cls){
         console.log('startTime:' + cls. startTime)
   }
}
// typeof / instanceof - 类型分类场景下的身份确认
function class(name:string, score:string | number){
     if (typeof score === 'number'){
         return 'teacher:' + name + ':' + score;
     } else if (typeof score === 'string'){
        return 'student:' + name + ':' + score;
     }
}
// instanceof
const getName = (cls:Class){
  if (cls instanceof Teacher){
      return cls.courses
  } else if (){
     return cls.startTime
  }
}
// 自定义类型 起个别的名字,更好认一点
 const isTeacher = function(cls: Teacher | Student):cls is Teacher {
   return 'courses' in cls
}
const getName = (cls:Teacher | Student)=>{
    if (isTeacher(cls)){
         return cls.courses
    }
}

8、TS 进阶

  • 函数重载 - 复用
   class Course {
     start(name:number, score:number):number;
     start(name: string, score:string):string;
     start(name: string, score: number): string;
     start(name: number, score: number): string;
     start(name: Conbinable, score: Conbinable){
          if (typeof name == 'string' || typeof score == 'string') {
               return 'student:' + name + ':' + score;
          }
     }
   }
   const course = new Course();
   course.start('小红', 5) 
  • 泛型 - 复用 (简单一句话: 类型可控)
  • 让模块可以支持多种类型数据 - 让类型声明和值一样,可以被赋值和传递
    function startClass <T, U>(name: T, score: U):T{
        return name + score;
    }
    console.log(startClass<Number, String>('小红', 5))
   // T、U、K - 键值、V - 值 、E - 节点、元素
  • 装饰器 - decorator 用处很大,通用性的操作
    // 1、类装饰器
    function decorator1(target:Function):void{
        target.prototype.startClass = function():void{
           // 通用功能
       }
     } 
   // 2、属性装饰器
    function propsWrapper(target:any, key:string){
       // 属性的统一操作
      Object.defineProperty(target, key,{
      })
    }
    // 3、方法装饰器 - target: Object, propertyKey:string, descriptor: TypePropertyDescript
    @decorator1
    class Course {
        constructor(){
          // 业务逻辑 
        }
        @propsWrapper
        public name:string;
         
        @methodDec
     }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349