TypeScript 小细节丨啊~? 两种函数声明居然还有差异?

作者: 水哥澎湃分类: 计算机技术 发布时间: 2024-02-13 09:09:53 浏览:9046 次

TypeScript 小细节丨啊~? 两种函数声明居然还有差异?

错位指针:
第二种是协变,符合里氏转换原则。第一种和里氏转换相悖。

沙勒垃圾之王:
方法形式的语法表示这个方法属于对象的实现的一部分,相当于默认这个方法的this为这个对象本身,而且是readonly,它的类型检查和c#关于逆变和协变的逻辑是类似的;变量形式的语法表示这是一个函数类型的变量,是read write并且this不存在/不需要考虑,所以要对变量的读写做严格的检查

【回复】回复 @水哥澎湃 :视频里都是对象字面量语法体现不出来,你试试给一个已知类型的变量给这个方法赋值,差距就出来了
【回复】我也是想着 箭头函数 没有this 无父无母的, 可能需要特殊对待, 没敢说[呲牙]
FlyingFatPenguin:
参数的 parent换成child ,TS报错是合理的,因为按照XXX的类型定义,外部调用的时候这里可以传入parent,而你的实现只处理child这一更具体的场景,没有考虑是parent而非child的情况,是可能引发异常的,这个就是参数的协变逆变问题。本质上你新定义的这个就不再是XXX的子类的,因为它违背了替换原则。单独写一个新类型,或者用as const就可以了。

【回复】1.我又想了一下. 觉得自己理解上错误的一点是: let 变量: 类型 = 值 事实上: 值的真实类型 没有覆盖 指定类型 2."不考虑是parent而非child", 因为希望TS能检查出来, 是这个希望没达成 两个类的foo内部都不应该考虑这些. (子类是父类的超集) 3."协变逆变"我目前不了解,回头会看看. "替换原则"我也会查查 视频中, 我是又写了一个类型 "as const" 可能对我有帮助, 谢了[脱单doge]
【回复】回复 @水哥澎湃 : 第一点还可以再了解一下 satisfies,应该会有双倍快乐
【回复】回复 @FlyingFatPenguin : 好的. 今天大致看了一下 satisfies , 英文的我都是看字幕, 回头再理解理解[呲牙]
bili_13075434948:
更具体的类型能当成更宽泛的类型用,method属于反直觉。对象初始化已经用xxx规定类型了,里面具体实现还想改类型,这操作本来就别扭,不怪ts,人家都推断好了。

【回复】"里面具体实现还想改类型", 这一点我本以为是有这样需求的... 容我再想想[脱单doge]
Euvtnenci:
按道理来说,接受子类相对于父类来说不是扩展而是收窄

【回复】既然我们费心思去利用 ts 类型系统,就不应该用这种 “anyscript” 的思想,去 hack tsc 的报错行为,至少不应该致力于写逻辑错误的代码。
【回复】回复 @食量堪比卡比兽 : [呲牙][打call]
【回复】回复 @水哥澎湃 :谢谢,我试了下你说的,就是TypeScript Vue Plugin这个插件
想个办法骂下up:
省流:建议对于编译器已经推断好的类型,没事别乱重新定义类型

【回复】想起了一个的笑话:测试用勺子反过来喝水,然后怪开发不会开发勺子。 很多东西就是人家编译器已经按照ts的规范,给你定好使用方法了,你非要把这个勺子反过来用,导致了一系列喝不到水的事故,怪不得经常能刷到一些xxx大厂放弃使用ts、各种唱衰ts的言论
【回复】回复 @King丶忆梦尘 :再有能力也会有疏忽的,有能力也是从没能力一步一步走过来的。总之就是,想提升自己,就用,尽量别用any,简历上会ts总比不会ts吃香
【回复】回复 @想个办法骂下up : 但就会发现一个问题,有能力的,不用ts也一样,没能力的ts也用不好,用成anyScript还不如不用。[辣眼睛],而且就像视频里这样随意更改已经规定好的类型,如果真这样做了所谓的开发时发现错误真的还有说服力吗。对于新手而言,遇到这种情况,可能都不明白为什么这个地方可以用的方法,换到另一个地方就不能用了[妙啊]
风飏:
C#里有个协变逆变的问题,就是专门讨论接口继承的时候参数/返回值的父类子类的问题。 像视频里这样,接口要求实现处理Parent,继承接口的obj只实现了处理Child,实际上obj并没有真正实现接口,因为obj不能处理非Child的Parent。 传参如此,返回值正好反过来。假如接口要求函数返回Child,而继承接口的obj返回Parent,实际上也是没有实现接口。[以闪亮之名_吃瓜]

丷杠上开花丷:
如果是这样的话,完全可以把 parent 再提取一个顶层接口 IC ,然后 parent 实现 顶层接口,child继承parent。 这样在定义xxx接口的时候,foo的参数类型是IC 不是就可以了么

【回复】回复 @水哥澎湃 : 如果是面向对象的思想 1. 类只是定义对象的属性和方法,而接口才是规范,定义的是规则。 所以现在的parent里你只是定义了属性name,child也只是定义了age。 2. 如果 parent和child都要定义方法而且要约束对应规则,按照面向对象的思想就需要接口用接口定义方法规范。parent和child分别去实现自身的方法。 3. 如果XXX是别人定义的,那更应该按照1,2 两点的思想去定义。这样才会让使用的人在使用的过程中不出现歧义,否则不是正好说明了XXX这个接口定义的并不完全面向对象么?
【回复】可能我没明白. 1. Parent 可以用一个接口限定, 但我觉得没必要, <类>本身就是个<约束> 2. 然后我还想假设 xxx 是别人定义的接口, 我不能直接修改 3. 我尝试 interface YYY extends XXX { }, foo会因为参数类型不同而直接报错
愤怒主义青年团团员:
子类型其实范围是收窄了。只实现Parent接口相当于把所有Object中符合Parent接口的过滤出来;而实现Child接口的,相当于把所有Object中符合Parent接口的过滤出来,然后再把符合Child接口的过滤出来。所以实际上是收窄了的。这一点比较反直觉,在大多数介绍里氏替换的文章里应该都有讨论。

不会起名随便输几个字:
这篇文章讨论了TypeScript中的一种编程模式——方法简写语法(Method Shorthand Syntax),并指出它可能导致运行时错误。文章通过一个具体的例子说明了问题:当一个方法期望的参数类型比实际传递的类型更严格时,TypeScript不会捕获到这个错误。为了解决这个问题,建议使用对象属性语法来定义方法,这样可以在类型不匹配时提前发现错误。文章还提到了一个ESLint规则,可以帮助开发者避免使用方法简写语法。最后,文章提到虽然方法简写语法在某些情况下可能有用,但大多数情况下应该避免使用。

谁敢来此人间:
通常而言,函数是用来封装功能的,所以 ts 就使用函数类型表达式来表示;因为,js 的函数有声明函数的写法和函数表达式的写法以及函数表达式箭头函数的写法;但是,在 js 中函数也是对象,尤其在 es5 中,函数可以作为构造函数来实例化对象,而且函数(函数也是对象)也可以添加属性和方法,这样用函数类型表达式就不能很好的描述函数是对象的特征,所以才有调用签名的写法;不过,常规的函数类型表达式写法就满足常规的开发,谁让 js 是个缝合怪尼?https://aexiar.github.io/web-design/notes/07_TypeScript/02_xdx/#_5-2-1-调用签名-call-signatures

【回复】这个链接记下来, 有时间我会看[呲牙]
火苗A型机:
我网上找了找,发现这个现象在[这里][1]的最后一段提了一下。 然后我实验的时候发现个有趣的事情。视频里这个现象的本质,不是编译器在检查 method 处...

【回复】我现在的功力还读不太明白你这个截图. 以后我再回来看[脱单doge]
【回复】补充一下,这里说的函数类型与“方法类型”的不同应该只在编译器内部不同。但表面上他们是相同的类型(即两种类型的变量可以相互赋值)
請終初我:
讲的非常棒啊,之前原作者文章没看懂啥意思,up讲了之后能听明白了,而且后面up的思考也很不错,是我想要的效果

【回复】谢谢肯定. [呲牙] 没想到有人看过原作者文章了. 我的"加工处理"能被看到,更是欣慰[呲牙]
AI头脑风暴:
夸夸:... 关键词:函数类型 书写方式 参数范围 差异 化窄 可宽 实例 子类 父类 接口 总结:TypeScript中对函数进行类型声明有两种方式:函数简写形式和属性形式。函数简写形式的参数范围既可宽可窄,而属性形式的参数范围只能宽不能窄。在实际编码中,函数简写形式的函数可以传递子类实例给要求父类实例的接口,而属性形式的函数则不可以。 - Powered by https://brainstorm.cool 下一代 AI 搜索引擎

SJBGC:
父子类那个问题已经修复了[妙啊][妙啊]

前端 typescript

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!