typescript设置默认值_一定要用Typescript么?

ed8c95b16ae6d6297e093add812cfc12.png

首先,声明几点:

  1. Typescript 必须学,属于前端和中间件开发的基本技能,这个没得谈
  2. 以下所称不需要 Typescript 的场景,均为特定场景,并非贬低 Typescript
  3. 成本收益考量是基础,并不是说一项技术不好,而是从其中获取的收益,没有付出的成本高

有这几个基础点,再来讨论这个问题 ——

使用Typescript一定会更好么?


静态类型 vs 动态类型

静态类型一定比动态类型好,这句话没问题

因为问题出现在编译期,一定比出现在运行时要更方便调试

但是这个问题在前端不完全成立,因为前端不覆盖全部逻辑,简而言之:

  1. 数据源不在你这,写入和读取的类型限制更不在你这,前端没有orm
  2. any,null,undefined 存在,会加大初始化难度,类型完备很难实现

这个场景和后端不同,在后端,你可以明确地说,静态类型>>动态类型,静态类型一时爽,代码重构火葬场

因为数据库结构,你可以用orm定义,既然定义权在你这,那么读取到的数据,绝大部分情况下,都不会出现意外,除了接口部分,需要用到校验(注意校验,之后还会讨论),从数据源到接口的整个类型链条,中间不会断裂,并且可选类型和any出现的情况很少,很多语言直接就没有

因此,这个静态类型和动态类型的比较还远没有结束:

静态类型>>动态类型≈错误的静态类型>>>>毫无约束的运行时

很多Typescript使用者,很想实现第一种情况,然而,如果因此划向了第三种,甚至第四种情况,那就真的得不偿失了

Typescript没有报错,但是却在运行阶段出现了奇奇怪怪的错误,此时你该如何进行调试呢?

是,解决方案有:

  1. 禁止写入any
  2. 一系列方案处理初始化
  3. 抽象开发,将逻辑静态化(提倡面向对象,函数式)

这些,是你需要针对Typescript付出的成本,同时,Typescript带来的可读性降低,更是成本之一,这个现象在React中更加严重,比如泛型和标签,同时,配置成本也是成本之一,只是不那么重要罢了

得到的优势是什么?

  1. 编译期类型错误提示
  2. 接口,类型提示方便团队协作
  3. 编译器掌握更多信息,可以优化性能
  4. 通过构建目标设置,可以实现跨平台(当然js通过响应工具也能实现,但是ts更加游刃有余)

四个优势,第三点聊胜于无,性能的小幅度提升影响不会很大,第四点和第二点,只对大型项目起作用(跨平台必然大),因此,在中小型项目中,所有问题都集中在了第一点 —— 编译期类型错误提示

但是,有一个很奇怪的问题是:

解决类型错误调试只有这一条解法么?

并不是!

首先,大部分的类型错误,实际上是发生在初始化阶段

Cannot read property 'xxx' on undefined

'undefined' is not an object:undefined

null is not an object

'undefined' is not a function

Object doesn't support property

Cannot read property 'length'

cannot set property of undefined

或者说这种情况下,问题与其说是类型错误,不如说是初始化处理方式错误

正常的情况下,大家直接想到的,处理初始化问题的方式,就是 ——

设置默认值

const DataContext = createContext({
  name:"",
  password:"",
  setName:"",
  setPassword:""
})
const data = useContext(DataContext)
// data.name data.password

这是 React 的做法,很多使用 React + typescript 的开发者,很自然地写出 createContext(),createContext(null) 的代码,在 Typescript 中是没有问题的,因为使用时必然是已经初始化了的(useContext 必然 在 createContext 下出现)

但是在 JavaScript 中,有这个初始值在,data. 后,就会亲切地出现 name 了

另外有意思的事,Typescript 并没有解决初始化问题,但是却将初始化问题更加方便地暴露在你面前

当然,Typescript 的反射更能帮助解决初始化,前提是 class+装饰器+反射 实现的依赖注入

constructor(someData:SomeData){
  // someData.a , someData.b
}

因此,反复审视,你使用的技术栈有提供这方面的支持么

剩下的部分,是可变类型

string -> number

SomeClass -> AnotherClass

这种看似 Typescript 是唯一解法,然而有意思的是,大家忽略了另外一个相当强势,并且根本上解决问题的方式 ——

校验

{
  optionalArray: PropTypes.array,
  optionalBool: PropTypes.bool,
  optionalFunc: PropTypes.func,
  optionalNumber: PropTypes.number,
  optionalObject: PropTypes.object,
  optionalString: PropTypes.string,
  optionalSymbol: PropTypes.symbol,
}

经过校验的数据,一定会是这个类型

注意,是一定

不论是编译期,还是运行时,都改变不了这个数据的格式!

一旦代码得以运行,相关数据必然是如此格式,这才是真正的类型安全!

所以,之前后端在处理前端接口问题时,采用的校验方式,其实也是主要方式之一

你当然可以 proto - grpc 来解决服务间交互,直接 http + 校验也并无不可


当然,如果出现人为的数据类型变更,Typescript 的优势就无可替代了

自动判定的可选类型,交叉类型,可以让你在开发时更加游刃有余

但是注意,这其实也是个成本问题,为何如此?因为其导致的后果,仅仅是数据类型变更时的小心翼翼,甚至添加动态校验,以及交叉,可选类型时,需要手动使用 class 的继承特性来处理

另外,如果由于数据变更导致的错误,Typescript能够有更直观的错误,而校验做不到更加细致,只能大致告诉你,问题出在哪个组件,哪个函数,会加大开发负担


综上分析,细致来下,在中小型项目中,Typescript 的优势是:

  1. 处理数据类型变更
  2. 重构提示

带来的负担是:

  1. 可读性降低
  2. 架构设计负担加重
  3. 开发负担增加

这就像是个天平,如果左边的优势压过了右边的负担,那么Typescript就会成为推荐,反之则反

所以,一旦能够降低这里的负担出现的情况,那就可以直接选择Typescript不带犹豫

  1. 有依赖注入,框架帮你解决数据和类型的获取问题,框架帮你解决初始化问题
  2. 类型完备,绝大部分api没有any,没有unknown,没有可选,没有交叉,判定过程框架帮你完成
  3. 采用 class 进行构建,充分运用 Typescript 的反射,类型判断,装饰器的功能,增加可读性,最好不要有JSX,html的归html,ts的归ts

有了这些,当优势压过负担,那么Typescript就可以顺理成章成为必选项了

另外, TypeScript 也不会取代 JS,前者只是 JS 的一个超集。我个人认为,JS 与 TS(带类型的超集)并行发展才是最合理的未来方向,而且这一点在可预见的未来不会改变 —— 尤雨溪
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值