TypeScript中的参数是否可能是错误的类型?
在JavaScript中:TypeScript中的参数是否可能是错误的类型?,typescript,Typescript,在JavaScript中: function doSomething(mybar) { if (!(mybar instanceof Bar)) throw new TypeError("mybar"); // ...other guard clauses } 在TypeScript中: function doSomething(mybar: Bar) { // is guard clause ALWAYS redundant? // ...other guard clause
function doSomething(mybar) {
if (!(mybar instanceof Bar)) throw new TypeError("mybar");
// ...other guard clauses
}
在TypeScript中:
function doSomething(mybar: Bar) {
// is guard clause ALWAYS redundant?
// ...other guard clauses
}
我喜欢用guard子句验证输入。所以在JavaScript中,我会测试mybar
是Bar
的一个实例,如果不是,我会抛出一个TypeError
在TypeScript中,mybar
是否保证为正确的类型?(从而消除了对第一保护条款的需要)
更新 下面有几个很好的答案,从“绝对可能”到“可能发生”到“不可能发生”
因此,也许一个表达问题的好方法是——如果可能在运行时提供了错误的类型,那么发生这种情况的机制是什么?例如,类型转换中的一个错误?在TypeScript中的工作方式与JavaScript不同,使用TypeScript时,如果您传递的参数不是函数签名中指定的类型,则在编译过程中会出错,因此您必须遵循函数参数的确切类型。这取决于您的函数。如果它是一个私有函数,只有您有权访问它,那么TS可以帮助确保它在编译时始终是正确的类型。如果它是一个公共功能,应该由另一个用户/方使用,那么如果您希望具有一定的弹性,则需要进行检查
TS类型是关于设计你的软件,不管你设计得有多好,如果用户选择以错误的方式持有它,它就会崩溃。因此,只在少数公共场所公开,并在那里进行检查。
instanceof
是一项测试,测试对象是否是条码的实例。这意味着参数的类型也是Bar
,反之则不一定正确。Typescript使用结构类型,因此任何具有Bar
结构的对象都将与函数参数兼容。因此,该代码完全有效:
class Bar {
bar: number;
}
function doSomething(p: Bar) { }
doSomething({
bar: 10
})
当您拥有私有属性时,您不能如此轻松地“伪造”对象,但即使如此,我们始终可以断言任何
:
class Bar {
private bar: number;
}
function doSomething(p: Bar) { }
doSomething({ // error now
bar: 10
})
doSomething({ // breaking out of type safety
bar: 10
} as any)
如果您的代码库不完全是TS,那么任何类型的安全性都会消失,JS可以随意调用您的TS函数
这是否意味着您应该始终包括支票?我会反对它。JS的类型非常松散(TS也是如此),这正是用户所期望的。如果它像鸭子一样嘎嘎叫,那就是鸭子,老JS咒语是这样的。如果对象具有与您的函数一起使用的属性,则无论它是如何创建的,它都应与您的函数一起使用。要回答您更新的问题:
如果在运行时可能提供了错误的类型,那么
发生这种情况的机制是什么?计算机打字中的一个错误
例子
有几种方法可以实现:
doSomething
是从JavaScript文件调用的(没有checkJs
或@ts check
)
- 提供了一个类似于
Bar
的对象。它在结构上是相同的,但它不是Bar
的实例
- 另一个开发人员将类型不正确的参数强制转换为
Bar
- 类型不正确的参数被自动强制转换为
any
(缺少类型定义,类型推断丢失)
- 错误类型的参数被写得不好的类型保护程序断言为
Bar
- 不正确类型的参数被视为
Bar
,因为它的定义在项目中的其他地方被扩充了
- 您的代码是在没有构建管道的环境中发布和使用的,因此不可能存在编译时错误(例如,作为UMD包分发)
- 使用不存在的键对对象或数组进行了索引(TypeScript假定它永远不能是
未定义的
)
- 在混合中使用了标准库中有问题的类型部分(例如,
Promise.resolve.call(1)
将在运行时抛出,即使TypeScript接受它)
是和否。您不能保证代码的来世。linter/hinter和transpiler将检查您的类型,但在运行时没有任何东西会执行相同的操作。但是正如上面@ZorgoZ所解释的,在运行时代码仍然会出现错误行为?或者这永远不会发生吗?@Ionix我自己已经使用TS超过4年了,从未遇到过任何代码行为错误的情况,即使在函数定义中指定了参数类型。:)这听起来像是专家的建议,所以我谢谢你!:-)好建议。然而,如果该公共代码也是由我编写的,并且也通过ts transpiler,那么如何能够提供错误的类型呢?发生这种事情的机制是什么?那么你不需要重复检查,你只需要学习信任TS,就像你编写的函数一样。你的答案是好的,值得赞赏,但被接受的答案深入解释了潜在的技术细节。如果我必须诚实的话,我觉得答案离题了。但有些细微差别我不知道,所以我可能是错的。很高兴你通过这个网站发现了很多有用的东西,但QI没有意识到有这么多场景…非常彻底,非常感谢,谢谢!我将继续使用一个保护条款来确保安全。但是作为一个JavaScript开发人员,我遇到了同样的问题。如果没有对函数参数进行类型检查,typescript将无法在运行时抛出错误。在为类似情况编写单元测试时,ts编译器在测试文件中对我大喊大叫,说我传递了一个无效的参数,我故意这样做是为了抛出一个错误。处理这个问题的“打字脚本”方式是什么?是的,“和任何人一样”获救,但我觉得这有点骇人。