TypeScript常见基础面试题

TS有什么优点和缺点,适应场景是什么

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

缺点:

有一定学习成本
某些情况下,类型定义过于混乱,可读性不好
类型设计过于灵活和松散,且有“万恶”的any
应用不规范,则变成“anyscript”

适用场景:

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

TS的基础类型有哪些,数组和元组有什么区别

基础类型:
boolean
symbol
number
undefined
string
null
其他类型:
数组 Array和元组Tuple
枚举
对象和函数(一般是自定义的)
//数组单一类型
const arr1:number[]=[1,2,34,4]
const arr2:Array<number>=[10,20,30] //泛型
//元祖 多个类型
const x:[string,number]=['a',1]
//枚举(本质就是JS对象)
enum Color{
    Red,
    Green,
    Blue
}
const c:Color=Color.Blue
//对象和函数
interface User{
    name:string,
    age:number,
    sayHi:(a:string)=>{}
}

const user:User={
    name:'aa',
    age:90,
    sayHi(a){return a}
}

any void never unknown 区别

any : 不进行类型检查 比较危险的情况
void : 和 any 相反,没有类型 一般配合函数一起使用 function f1(): void {}
never : 永远不存在的类型  function err(message:string):never{throw new Error(message)}
unknown :未知类型 更加安全的any 
// as 手动类型转换,告诉 TS 编译器:我知道 b的类型,我对安全负责
const b: unknown = 100
;(b as string).length

TS 访问修饰符有哪几个?

public (默认)-全部可访问
protected - 自己和派生类可访问 派生类就是继承自己的类
private - 只有自己可访问

代码演示

class Person {
  public name: string = ''
  protected age: number = 0
  private girlFriend: string
  constructor(name: string, age: number) {
    this.name = name
    this.age = age
    this.girlFriend = '小张'
  }
}
class Employee extends Person {
  constructor(name: string, age: number) {
    super(name, age)
  }
  public getInfo() {
    console.log(this.name)
    console.log(this.age)
  }
}

const x = new Employee('x', 200)
console.log(x.name)
//面向对象三大要点:继承 封装 多态(函数重载)



TS私有属性# 和 private 有什么区别

# 属性,不能在构造函数参数中定义
private 属性,可通过as any 强制获取,但#属性不行
class Person {
  #salary: number
  constructor(private name: string, salary: number) {
    this.#salary = salary
  }
  print() {
    console.log(this.#salary)
    console.log(this.name)
  }
}
const p = new Person('x', 5000)
console.log((p as any).name)

TS中type和interface有何区别,如何选择

type和interface的共同点:
都可以描述一个对象结构
都可以被class实现
都可以被扩展
interface UserInfo {
  name: string
  age: number
  getName: () => string
}

const userInfo: UserInfo = {
  name: 'zs',
  age: 90,
  getName() {
    return 'sss'
  }
}
console.log(userInfo.age)

//使用type

type UserType = {
  name: string
  age: number
  getName: () => string
}

const userType: UserType = {
  name: 'zs',
  age: 90,
  getName() {
    return 'ttt'
  }
}

class UserClass implements UserInfo {
  name = 'ccc'
  age = 20
  getName() {
    return 'aaa'
  }
}
class UserTypeCLass implements UserType {
  name = 'ccc'
  age = 20
  getName() {
    return 'aaa'
  }
}
type 和 interface 不同点
type 可以声明基础类型
type 可以使用联合类型 交叉类型
type 可以通过 typeof赋值
//type 可以定义基础类型 interface不行
type name = string
type list = Array<string>

总结: type 和 interface 如何选择


初衷:type 定义类型关系,interface 定义数据结构;
但实际使用时,很多时候会模糊不清,没有明确的界限
我的建议:优先使用interface,再使用type(简单明了)

type 和 interface 如何扩展属性?

interface 可以合并重名声明 type 不可以
interface myUser {
  name: string
}
interface myUser {
  age: number
}
//使用
const myuser: myUser = { name: 'zhangsan ', age: 90 }
console.log(myuser.age)

interface 扩展interface / type

interface User1 {
  name: string
}
interface User2 extends User1 {
  age: number
}
const u2: User2 = { name: 'zhangsan ', age: 90 }

//type 也可以通过extends扩展
type User1 = {
  name: string
}
interface User2 extends User1 {
  age: number
}
const u2: User2 = { name: 'zhangsan ', age: 90 }

// type 扩展type / interface

type User3 = {
  name: string
}

type User4 = User3 & {
  age: number
}
const u3: User4 = { name: 'zhangsan ', age: 20 }
//interface type相互扩展
interface User3  {
  name: string
}
type User4 = User3 & {
  age: number
}
const u3: User4 = { name: 'zhangsan ', age: 20 }
console.log(u3)

【附】type 和 interface 的问题,是 TS 设计问题

初衷是好的,但实际使用时引起“选择困难症”引来社区争吵
就像 Vue3 的 ref和 reactive(再对比 React的state和 ref )
好的设计,应该简单明确,而不是设计混乱并说是你不会用

TS 的泛型 Generics 是什么?

//泛型定义到函数 
function fn<T>(arg: T): T {
  return arg
}
const x = fn<number>(100)
//定义数组
const list: Array<number> = [10, 30]
//定义接口
interface userP {
  name: string
  age: number
}
const userp: Array<userP> = [{ name: 'xxx', age: 88 }]
//多个类型
function fn1<T, U>(a: T, b: U) {
  console.log(a, b)
}
fn1<string, number>('x', 10)
//定义在class
class SomeClass<T> {
  name: T
  constructor(name: T) {
    this.name = name
  }
  getName(): T {
    return this.name
  }
}
const s1 = new SomeClass<string>('xxx')
const s2 = new SomeClass<number>(888)

//定义在 type

function fn<T>(arg: T): T {
  return arg
}
const myFn1: <U>(arg: U) => U = fn

// 定义在接口
interface F2<T> {
  (arg: T): T
}
const myFn2: F2<number> = fn

泛型的使用


// 泛型 可以传入任何类型
interface UserPerson {
  name: string
  age: number
}
const u = fn<UserPerson>({ name: 'xx', age: 10 })
console.log(u, 'uuuuu')

//泛型 可以当做任何类型来使用
function fn3<T>(arg: Array<T>) {
  console.log(arg)
}
fn3<string>(['x'])
fn3<number>([20, 30])

// 泛型的扩展属性
interface F5 {
  length: number
}
function fn4<T extends F5>(arg: T) {
  console.log(arg.length)
}
fn4<string>('xxxx')
fn4<number[]>([10, 23])

总结泛型

泛型Generics,是为了通用性和扩展性
泛型定义:函数class interface type
泛型使用:传入任何类型,当做任何类型,扩展其他属性

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

交叉类型
	多个类型合并为一个类型T1 & T2 & T3
interface U1 {
	  name: string
	  age: number
}
interface U2 {
  city: string
  age: number
}
//交叉类型
type UserType1 = U1 & U2

//可获取U1 U2的所有属性(并集)

interface U1 {
  name: number
  city: string
}
interface U2 {
  name: string
  age: number
}
//如果属性类型冲突了 那该属性类型是never
//交叉类型(整合U1 U2的所有属性 并集)
type UserType1 = U1 & U2
const userTest: UserType1 = { name: 'x', city: 'beijing', age: 20 } //注意这里


在这里插入图片描述
要解决上面的问题 需要主动去规避

interface U1 {
  name: string
  city: string
}
interface U2 {
  name: string
  age: number
}
//交叉类型(整合U1 U2的所有属性 并集)
type UserType1 = U1 & U2
const userTest: UserType1 = { name: 'x', city: 'beijing', age: 20 }

基础类型不能交叉 返回never 没有任何意义

type Tx = string & number  //返回never 没有任何意义

联合类型

联合多个类型 T1·| T2|T3 ,
一种“或”的关系
**基础类型可以联合**
interface U1 {
  name: string
  city: string
}
interface U2 {
  name: string
  age: number
}
//在函数使用
function fnT(): U1 | U2 {
  return {
    name: 'x',
    age: 90
  }
}
type Tx = string | number
const xxx: Tx = 100
//错误写法
function fn9(a: string | number){
  console.log(a.length) //这里会报异常
}

TS中有哪些特殊符号,分别是什么意思-part1

TS 特殊符号? ?. ?? ! _  &| #

? 表示可选 
interface PersonInfo {
  name?: string
  age: number
}
const P: PersonInfo = { age: 888 }
function Perosns(a: number, b?: number) {
  console.log(a, b)
}
Perosns(10) // 10 undefined
?. 表示可选链
const infoD: any = {
  info: {
    city: '北京'
  }
}
const city = infoD?.info?.city

?? 表示空值合并运算符(只有左侧是null或者undefined 才会返回右侧 补齐 ||)

const user2: any = {
  name: '张三',
  index: 0
}
const n1 = user2.name ?? '暂无'
const n2 = user2.name || '暂无'
const index1 = user2.index ?? '暂无index'
const index2= user2.index || '暂无index'
console.log(index1 ,index2) // 0 '暂无index'

! 表示非空断言操作符号
function fun(a?: string) {
  return a!.length // 加! 表示你已经知道了a不会是undefined
}
_ 表示数字分隔符
const millon = 100_000_111

总结一下

? 可选属性/参数
! 非空断言符
?.可选链
_ 数字分隔符
?? 空值合并运算符
其他 & | #

TS常见的工具类型有哪些

Partial<T>
interface CityInfo {
  name: string
  age: number
  city: string
}
//使用 Partial 
const u: Partial<CityInfo> = { name: 'x', city: 'dkd' }
//类似于这样的可选结构
interface CityInfo {
  name?: string
  age?: number
  city?: string
}

Required<T>

interface CityInfo {
  name: string
  age: number
  city: string
}
// Required 必填 少一个都不行
const u: Required<CityInfo> = { name: 'x', city: 'dkd', age: 99 }

Pick<T,K> 选取一个或者多个
interface CityInfo {
  name: string
  age: number
  city: string
}
const u: Pick<CityInfo, 'name' | 'age'> = { name: 'x', age: 99 }
//使用
type CityType = Pick<CityInfo, 'name'>
const city1: CityType = { name: 'ddd' }

Omit<T,K>  剔除几个属性 忽略几个
//剔除 city属性
type CityType2 = Omit<CityInfo, 'city'>
const city2: CityType2 = { name: 'ddd', age: 222 }

ReadOnly<T>  设置每个属性为只读
type CityType3 = Readonly<CityInfo>
const city3: CityType3 = { name: 'xx', age: 90, city: 'ddd' }
//CityType3.name='333' 这里就报错了
const 和 readonly 区别

const 和 readonly 区别

 const 定义单独的变量
 readonly 定义属性

TS如何扩展window属性?

declare interface Window {
  test: string
}
Window.test='xxx'

TS 如何扩展一个对象的属性?

interface Obj {
  [key: string]: any
}

const obj: Obj = {
  a: 10,
  b: 20
}
obj.d = 30
obj.c = '90'

TS中如何定义第三方模块的类型?

现在很多插件都是直接用TS 开发的,本身包含了类型定义
常见的第三方插件,都有 @types/xxx包,安装即可使用
其他的,可通过declare module定义类型
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值