最新要闻
- TypeScript 程序员晋级的 11 个必备技巧
- 观焦点:奕东电子:截止2023年4月20日,公司股东户数为24990户
- 新光光电去年净利亏损2467万元 2019年上市募资9.5亿
- 今日视点:番石榴上火吗_吃番石榴不会上火
- 尽管食品价格创历史新高 但通货膨胀率降至 10.1%
- 全球实时:农业农村部:开展农村改厕“提质年”工作
- 天津打造夜间消费新场景 "五一"假期夜间经济亮点纷呈
- 揭秘《如懿传》“乌拉那拉氏”断发谜团,抽丝剥茧再现事件始末
- 华科大团队在里德堡原子量子信息领域取得重要进展 消息
- 首宗封顶!松山湖王者归来!楼面价26000元,金地的
- 东吴证券:给予中金黄金买入评级-当前速看
- 研究生统考科目有哪些_考研考什么科目
- 一公分是多少毫米?_一公分
- 90后温商卖螺钉替父还债千万,科腾精工背靠海尔冲刺A股 全球看点
- 汇宇制药(688553.SH):氟维司群注射液获得药品注册证书-全球最资讯
- A股申购 | 经纬股份(301390.SZ)开启申购 位处电力工程技术服务行业第二梯队
5G

首例5g乳腺手术价格是多少钱?首例5g乳腺手术成功率是多少?

电信光纤多少钱一年?电信光纤价格表
- 首例5g乳腺手术价格是多少钱?首例5g乳腺手术成功率是多少?
- 电信光纤多少钱一年?电信光纤价格表
- 5g流量消耗会不会很快?手机打开5g好还是关闭5G好?
- 5g怎么变成4g信号?5g手机排名前十名一览
- 5g和4g的区别在哪里?5g首批城市名单
- 5g是谁最先研发出来的?5g是什么意思?
科技
TypeScript 程序员晋级的 11 个必备技巧
当你学习TypeScript时,你的第一印象可能会欺骗你:这不就是JavaScript注解的一种方式吗?不就是编译器用来帮助我找到潜在bug的吗?
(资料图)
虽然这种说法没错,但随着你对TypeScript不断了解,你会发现这门编程语言最不可思议的力量在于编写、推断和操作数据类型。
本文总结的一些技巧,可以帮助大家充分发挥TypeScript的潜力。
#1 用集合的概念思考问题数据类型是程序员日常要处理的概念,但要简洁地定义它却出奇地困难。然而我发现集合非常适合用作概念模型。
刚开始学习TypeScript时,我们常常会发现用TypeScript编写类型的方式很不自然。举一个非常简单的例子:
type Measure = { radius: number };type Style = { color: string };// typed { radius: number; color: string }type Circle = Measure & Style;
如果你在逻辑AND的意义上解释运算符&,可能会认为Circle是一个虚拟类型,因为它是两种类型的结合,没有任何重叠的字段。这不是TypeScript的工作方式。此时通过集合的概念思考更容易推断出正确的行为:
每个类型都是一系列值的集合。有些集合是无限的:例如string、object;有些是有限的:例如bool,undefined,...unknown是通用集(包括所有值),而never是空集(包括无值)。类型Measure是包含radius数字字段的所有对象的集合。style也是如此。&运算符创建一个交集:Measure & Style表示包含radius和color的对象集,这实际上是一个较小的集合,字段更常用。同理,|运算符创建一个并集:一个较大的集合,但常用字段可能较少(如果组合两个对象类型的话)。集合还有助于了解可分配性:仅当值的类型是目标类型的子集时,才允许赋值:
type ShapeKind = "rect" | "circle";let foo: string = getSomeString();let shape: ShapeKind = "rect";// disallowed because string is not subset of ShapeKindshape = foo;// allowed because ShapeKind is subset of stringfoo = shape;#2 了解声明类型和收窄类型
TypeScript中一个非常强大的功能是基于控制流的自动类型收窄。这意味着变量在代码位置的任何特定点都有两种与之关联的类型:声明类型和收窄类型。
function foo(x: string | number) { if (typeof x === "string") { // x"s type is narrowed to string, so .length is valid console.log(x.length); // assignment respects declaration type, not narrowed type x = 1; console.log(x.length); // disallowed because x is now number } else { ... }}#3 使用可区分的联合类型而不是可选字段
当定义一组多态类型(如Shape)时,很容易这样开始写代码:
type Shape = { kind: "circle" | "rect"; radius?: number; width?: number; height?: number;}function getArea(shape: Shape) { return shape.kind === "circle" ? Math.PI * shape.radius! ** 2 : shape.width! * shape.height!;}
需要非空断言(访问radius、width和height时),因为kind和其他字段之间没有建立关系。相反,可区分的联合类型是一个更好的解决方案:
type Circle = { kind: "circle"; radius: number };type Rect = { kind: "rect"; width: number; height: number };type Shape = Circle | Rect;function getArea(shape: Shape) { return shape.kind === "circle" ? Math.PI * shape.radius ** 2 : shape.width * shape.height;}
从以上代码可以看出,类型收窄消除了强制类型转换的需要。
#4 使用类型谓词避免类型断言如果你以正确的方式使用TypeScript的话,你会发现自己很少使用显式类型断言(比如value as SomeType);但是,有时你可能会冲动地写出诸如这样的代码:
type Circle = { kind: "circle"; radius: number };type Rect = { kind: "rect"; width: number; height: number };type Shape = Circle | Rect;function isCircle(shape: Shape) { return shape.kind === "circle";}function isRect(shape: Shape) { return shape.kind === "rect";}const myShapes: Shape[] = getShapes();// error because typescript doesn"t know the filtering// narrows typingconst circles: Circle[] = myShapes.filter(isCircle);// you may be inclined to add an assertion:// const circles = myShapes.filter(isCircle) as Circle[];
更优雅的解决方案是将isCircle和isRect更改为返回类型谓词,这样就可以帮助TypeScript在filter调用后进一步收窄类型:
function isCircle(shape: Shape): shape is Circle { return shape.kind === "circle";}function isRect(shape: Shape): shape is Rect { return shape.kind === "rect";}...// now you get Circle[] type inferred correctlyconst circles = myShapes.filter(isCircle);#5 控制联合类型的分布方式
类型推断是TypeScript的特性;大多数时候,它默默地为你工作。但是有时你可能对模棱两可的细微情况进行干预。分布式条件类型就是其中一种情况。
假设我们有一个ToArray辅助类,如果输入类型还不是数组类型,则返回数组类型:
type ToArray= T extends Array ? T: T[];
你认为以下类型会推断出什么?
type Foo = ToArray;
答案是string[] | number[]。但这是模棱两可的。为什么不是(string | number)[]呢?
默认情况下,当TypeScript遇到联合类型(此处为string | number)的泛型参数(此处为T)时,它会分布到每个组成部分中,这就是为什么会得到string[] | number[]的原因。你可以通过使用特殊语法并将T包装在一对[]中来更改此行为,例如:
type ToArray= [T] extends [Array ] ? T : T[];type Foo = ToArray ;
现在Foo被推断为类型(string | number)[]。
#6 使用详尽检查捕获在编译时未处理的情况在switch语句中使用enum枚举时,一个好习惯是在没有匹配到合适值的情况下主动抛错,而不是像在其他编程语言中那样默默地忽略它们:
function getArea(shape: Shape) { switch (shape.kind) { case "circle": return Math.PI * shape.radius ** 2; case "rect": return shape.width * shape.height; default: throw new Error("Unknown shape kind"); }}
通过使用never类型,静态类型检查就可以更早地查找到错误:
function getArea(shape: Shape) { switch (shape.kind) { case "circle": return Math.PI * shape.radius ** 2; case "rect": return shape.width * shape.height; default: // you"ll get a type-checking error below // if any shape.kind is not handled above const _exhaustiveCheck: never = shape; throw new Error("Unknown shape kind"); }}
有了这个,在添加新的shape种类时,就不可能忘记更新getArea函数。
该技术背后的基本原理是,除了never之外,不能为never类型分配任何内容。如果shape.kind的所有备选项都被case语句用尽,那么达到default的唯一可能类型是never;但是,如果未涵盖所有备选项,则将泄漏到default分支并导致无效分配。
#7 宁可使用type而不是interface在TypeScript中,type和interface是两种非常相似的数据结构,都可以用来构造复杂的对象的。虽然可能有争议,但我的建议是在大多数情况下始终使用type,仅在满足以下任一条件时才使用interface:
想利用interface的合并功能。有涉及类/接口层次结构的OO样式代码。否则,始终使用更通用的type构造会产生更一致的代码。
#8 只要合适宁可使用元组而不是数组对象类型是构造结构化数据的常用方法,但有时你可能希望使用更简洁的表示形式,而改用简单的数组。例如,Circle可以定义为:
type Circle = (string | number)[];const circle: Circle = ["circle", 1.0]; // [kind, radius]
但是这种构造是松散的,如果创建类似["circle", "1.0"]的内容很容易出错。我们可以通过使用元组来使其更严格:
type Circle = [string, number];// you"ll get an error belowconst circle: Circle = ["circle", "1.0"];
使用元组的一个很好的例子是React中的useState。
const [name, setName] = useState("");
既紧凑又类型安全。
#9 控制推断类型的通用性或特殊性TypeScript在进行类型推断时使用合理的默认行为,旨在使常见情况下的代码编写变得容易(因此类型不需要显式注释)。有几种方法可以调整其行为。
使用const缩小到最具体的类型let foo = { name: "foo" }; // typed: { name: string }let Bar = { name: "bar" } as const; // typed: { name: "bar" }let a = [1, 2]; // typed: number[]let b = [1, 2] as const; // typed: [1, 2]// typed { kind: "circle; radius: number }let circle = { kind: "circle" as const, radius: 1.0 };// the following won"t work if circle wasn"t initialized// with the const keywordlet shape: { kind: "circle" | "rect" } = circle;使用satisfies来检查类型,而不影响推断的类型
请看以下示例:
type NamedCircle = { radius: number; name?: string;};const circle: NamedCircle = { radius: 1.0, name: "yeah" };// error because circle.name can be undefinedconsole.log(circle.name.length);
有个错误,这是因为根据circle的声明类型NamedCircle,name字段确实可以未定义,即使变量初始值设定项提供了字符串值。当然,我们可以删除:NamedCircle类型注释,但这将松散对circle对象有效性的类型检查。进退两难。
幸运的是,Typescript 4.9引入了一个新的satisfies关键字,它允许你在不更改推断类型的情况下检查类型:
type NamedCircle = { radius: number; name?: string;};// error because radius violates NamedCircleconst wrongCircle = { radius: "1.0", name: "ha" } satisfies NamedCircle;const circle = { radius: 1.0, name: "yeah" } satisfies NamedCircle;// circle.name can"t be undefined nowconsole.log(circle.name.length);
修改后的版本具有两个优点:对象字面量保证符合NamedCircle类型,推断类型具有不可为空的名称字段。
#10 使用infer创建额外的泛型类型参数在设计实用工具函数和类型时,你经常会觉得需要使用从给定类型参数中提取的类型。在这种情况下,infer关键字就可以派上用场。它可以帮助快速推断新的类型参数。下面是两个简单的例子:
// gets the unwrapped type out of a Promise;// idempotent if T is not Promisetype ResolvedPromise= T extends Promise ? U : T;type t = ResolvedPromise >; // t: string// gets the flattened type of array T;// idempotent if T is not arraytype Flatten = T extends Array ? Flatten : T;type e = Flatten ; // e: number
infer关键字在T extends Promise
TypeScript提供了强大的类型操作语法和一组非常有用的实用程序,可帮助你将代码重复减少到最低限度。以下是一些简单示例:
与其重复字段声明:
type User = { age: number; gender: string; country: string; city: string};type Demographic = { age: number: gender: string; };type Geo = { country: string; city: string; };
还不如使用pick实用程序提取新类型:
type User = { age: number; gender: string; country: string; city: string};type Demographic = Pick;type Geo = Pick ;
与其复制函数的返回类型:
function createCircle() { return { kind: "circle" as const, radius: 1.0 }}function transformCircle(circle: { kind: "circle"; radius: number }) { ...}transformCircle(createCircle());
还不如使用ReturnType
function createCircle() { return { kind: "circle" as const, radius: 1.0 }}function transformCircle(circle: ReturnType) { ...}transformCircle(createCircle());
与其并行同步两种类型的shape(此处为config类型和Factory):
type ContentTypes = "news" | "blog" | "video";// config for indicating what content types are enabledconst config = { news: true, blog: true, video: false } satisfies Record;// factory for creating contentstype Factory = { createNews: () => Content; createBlog: () => Content;};
还不如使用映射类型和模板字面量类型根据config的形状自动推断正确的factory类型:
type ContentTypes = "news" | "blog" | "video";// generic factory type with a inferred list of methods// based on the shape of the given Configtype ContentFactory总结> = { [k in string & keyof Config as Config[k] extends true ? `create${Capitalize }` : never]: () => Content;};// config for indicating what content types are enabledconst config = { news: true, blog: true, video: false } satisfies Record ;type Factory = ContentFactory ;// Factory: {// createNews: () => Content;// createBlog: () => Content; // }
这篇文章介绍了一系列TypeScript语言的高级应用。在实践中,你可能会发现直接这样用并不常见;但是,这些技术被大量用于那些专门为TypeScript而设计的库:如Prisma和tRPC。了解这些技巧可以帮助你更好地理解这些工具是发挥其威力的。
关键词:
-
-
-
-
TypeScript 程序员晋级的 11 个必备技巧
哪个关键词与你紧密相关?从一季度经济数据看生活消费
天海防务(300008)新增【太赫兹】概念 即时看
观焦点:奕东电子:截止2023年4月20日,公司股东户数为24990户
外交部发言人:敦促美国等发达国家审慎评估自身经济金融政策外溢影响-天天微速讯
抖音注册中长视频APP青桃商标
午评:两市走低 中药、贵金属板块涨幅居前-全球快消息
新光光电去年净利亏损2467万元 2019年上市募资9.5亿
日本加紧强化军事“桥头堡” 冲绳何时可获安宁?
兴业证券(601377.SH):股票期权做市业务资格获批_天天快报
当前观点:天牛是什么动物_天牛是什么
今日看点:一种可再生的工程细胞产品显示出治疗神经退行性和视网膜疾病的潜力
今日视点:番石榴上火吗_吃番石榴不会上火
立冬祝福问候语大全_立冬祝福语文案大全
全球播报:diagnostics policy service 占用率_diagnostics
今日热门!ProCook 第四季度收入下降
尽管食品价格创历史新高 但通货膨胀率降至 10.1%
天天速讯:华致酒行:进口酒近些年势头持续上涨,销售氛围良好
雨来了,沙尘退退退→→→
全球观热点:四川省万源市发布强降温橙色预警
全球实时:农业农村部:开展农村改厕“提质年”工作
浮盈2000亿,公募慎对TMT-世界即时看
山西培育壮大农业龙头企业 推动"特""优"农业发展
天津打造夜间消费新场景 "五一"假期夜间经济亮点纷呈
古人如何为孩子压惊?有的方法还在用,有的方法已经失传了_新动态
揭秘《如懿传》“乌拉那拉氏”断发谜团,抽丝剥茧再现事件始末
环球快资讯:【南篱/黄金】至于黄金能不能见顶?
每日消息!4月20日汇丰石化硫磺报价下调
环球热文:为新入选市级专家“上门颁奖”
二刷《尘封十三载》,顿悟卫峥嵘才是造成两个女人不幸的“原罪”
钢花街代办服务暖心 残疾人足不出户拿到乘车证_世界最资讯
华科大团队在里德堡原子量子信息领域取得重要进展 消息
上海2023年首轮土拍首日:有人戴红围巾进场,有房企经营执照范围未通过核验
首宗封顶!松山湖王者归来!楼面价26000元,金地的
新北市一家当铺遭人开40余枪 枪手向警方主动投案
异动快报:ST鹏博士(600804)4月20日14点44分触及涨停板
东吴证券:给予中金黄金买入评级-当前速看
欧冠疯狂一夜:皇马2-0切尔西,AC米兰1-0改写17年历史,4强浮现
【环球速看料】龙虎榜丨7.65亿资金抢筹蓝色光标,机构狂买工业富联(名单)
全球快看点丨鸟妈妈惊跑,20米高废电塔上留下一窝雏鸟……
阿修罗高清在线播放2018_阿修罗2018在线观看hd高清版
重庆到宜昌三峡游轮有几个景点_重庆到宜昌三峡游 世界观速讯
研究生统考科目有哪些_考研考什么科目
每日热议!幸福是奋斗出来的感想_感想是什么意思
全球头条:雷霆纳克多久刷一次_雷霆纳克
一公分是多少毫米?_一公分
最新消息:苹果余额宝收益4%?我可一点都不羡慕
首季经济形势丨平稳运行、动能积蓄——透视首季工业经济数据-报资讯
每日速递:一季度农业农村经济运行情况:稳步提升粮食产能 全面推进乡村振兴
正式逮捕!-信息
北向资金今日净卖出9.16亿元 分众传媒、汇川技术等获加仓
90后温商卖螺钉替父还债千万,科腾精工背靠海尔冲刺A股 全球看点
上海市哪个省份?_上海市是哪个省-天天快资讯
北京一季度GDP同比增3.1%,人均消费支出同比增6.3%-全球热议
五洲特纸(605007.SH):2022年净利润下降47.41%至2.05亿元 拟10派1.6元_天天最资讯
汇宇制药(688553.SH):氟维司群注射液获得药品注册证书-全球最资讯
环球关注:宁愿去印度都不来中国!两大汽车巨头为何迟迟不愿在中国建厂?
BuzzFeed将关闭新闻部门,并裁员15%|天天消息
捷报频传!多家粤企在广交会签下百万美金订单
安车检测(300572.SZ):深耕机动车检测领域近二十年,在机动车检测产业链上下游积累了丰富的行业资源 环球热点
A股申购 | 经纬股份(301390.SZ)开启申购 位处电力工程技术服务行业第二梯队
打印机0x0000007e找不到指定模块_打印机0x0000007e
全球时讯:中国一季度经济数据说明什么?国际舆论深度解析
世界快资讯:华为阅读发布最新进展 月活用户超1亿
【民生在线】青岛-曼谷航线将于4月底复航 计划新开10个国内航点_今日热闻
全球新消息丨小米13 Ultra京东全版本卖断货!很多米粉跟员工要F码
用ChatGPT和强化学习玩转《我的世界》,Plan4MC攻克24个复杂任务 环球看热讯
世界热文:《中国农业展望报告(2023-2032)》发布
攸县物业管理实施细则
心理学哲学评论
心理学哲学研究
动态焦点:孕早期宫缩对胎儿影响_孕早期宫缩怎么回事
厦门-台北两岸“三通”跨境电商快线开通 天天热头条
泉州市“闽南厨娘”厨艺展示主题活动举办
G237金舒大道项目最新进展!
快讯!1号台风“珊瑚”生成!福州今起降温!
当前速递!图像同一性鉴定成为二审抗诉获法院改判的关键性新证据
法院执行:艰难的守望终会带来值得的收获_每日观点
午评:沪镍涨超4%,豆二跌超2%
股市小资金真正做大的唯一方式:“线上阴线满仓,线下阳线清仓”
网上群众工作新路径如何走?这个论坛来支招_每日时讯
2022年江苏人均每日阅读时长85.35分钟
央行:一季度房地产贷款增长呈上升态势
@全省7.7万考生,这项考试4月22日开考!考前注意→
【世界播资讯】楚阳是哪本小说的主角_楚阳
环球视点!花鸭借钱借款逾期52年拖欠多久上征信系统
省呗逾期七天拖欠多久会上征信系统 每日讯息
当前热议!住房公积金提取方式,变了!
突发!小米13 Ultra因成本增加或将上调定价,最低6299起,还香吗
产品结构优化叠加渠道红利释放,劲仔食品是下一个食品大牛股吗?
柳湖街道开展“国家安全教育日”主题周活动_世界观点
源汇区干河陈市场监管: 召开商户培训观摩会确保"舌尖安全"! 环球报资讯
天天快看:为社会救助打造"数据天网"!漯河这个"组"获省"五一巾帼标兵岗"
基础建设板块4月20日涨3.45%,龙建股份领涨,主力资金净流入1.62亿元|焦点速读
坠落的陨石去哪儿了?潮新闻带你去地质博物馆一探究竟 世界简讯
北京专报丨央行:当前住户部门的消费和投资意愿在回升,储蓄意愿在下降
宝宝树回应高管内讧:目前经营管理一切正常 每日快讯
今日热门!华为宣布实现自主可控的MetaERP研发和替换
世界滚动:“限温令”鱼目混珠,民进党当局能源政策还能硬拗多久?
"乙类乙管"政策实施百日 厦门高崎机场口岸出入境流量超55万人次 全球视讯