[英]No compile time error for Typescript type mismatch
I have a function defined like this:我有一个 function 定义如下:
export async function removeUser(deleteUserId: Types.ObjectId)
When I mistakenly called this function and pass a Mongoose object's id
parameter, which is a string, it triggered a runtime exception further in the code when I tried to use the .equals()
method which exists on an ObjectId but not on a string:当我错误地调用这个 function 并传递一个 Mongoose 对象的
id
参数时,它是一个字符串,当我尝试使用.equals()
方法时,它在代码中进一步触发了运行时异常,该方法存在于 ObjectId 而不是字符串上:
await removeUser(deleteUser.id);
When I corrected this by passing the ObjectId, everything worked fine:当我通过传递 ObjectId 更正此问题时,一切正常:
await removeUser(deleteUser._id);
My question is, why didn't I get a compile time error from Typescript if the argument is specified as an ObjectId, but a string is being passed?我的问题是,如果参数指定为 ObjectId,但传递的是字符串,为什么我没有从 Typescript 收到编译时错误?
Edit: I see that the .id
is defined as any
, not as a string
.编辑:我看到
.id
被定义为any
,而不是string
。 I suspect that will factor into the answer?我怀疑这会影响答案?
Yep, if we can somehow check for any , then we can make sure that values of type any
cannot be passed:是的,如果我们能以某种方式检查 any ,那么我们就可以确保不能传递
any
类型的值:
type IfAny<T, Y, N> = 0 extends (1 & T) ? Y : N;
export async function removeUser<Id extends Types.ObjectId>(deleteUserId: IfAny<Id, never, Id>) {
So if we pass in any
, the type of deleteUserId
will turn into never
:所以如果我们传入
any
, deleteUserId
的类型就会变成never
:
await removeUser(deleteUser.id); // error, type 'any' is not assignable to type 'never'
await removeUser(deleteUser._id); // ok
I see that the.id is defined as any, not as a string.
我看到 the.id 被定义为任何,而不是字符串。
Values of type any
allow assignment to any type. any
类型的值允许分配给任何类型。
const n: number = 'string' as any // fine
It's an escape hatch from the type system.这是类型系统的逃生舱口。 So
any
is not typesafe and should be avoided at all costs.所以
any
不是类型安全的,应该不惜一切代价避免使用。
The compiler effectively treats any as “please turn off type checking for this thing”.
编译器有效地将 any 视为“请关闭对此事物的类型检查”。 It is similar to putting an @ts-ignore comment around every usage of the variable.
它类似于在变量的每个用法周围放置一个@ts-ignore 注释。
Typescript types exist only in compile time, not in runtime. Typescript 类型只存在于编译时,不存在于运行时。 Therefore, Typescript type system is not sound -- it cannot guarantee you that if your program compiles, it will not throw any error in runtime.
因此,Typescript 类型系统并不健全——它不能保证如果您的程序编译通过,它不会在运行时抛出任何错误。
Back to your question, if a variable type is any
, you can do anything with it, and Typescript will not even blink.回到你的问题,如果一个变量类型是
any
,你可以用它做任何事情,而 Typescript 甚至不会眨眼。 You should use any
type with an extreme caution.您应该极其谨慎地使用
any
类型。
For example, if you have a variable obj
of type any
:例如,如果您有一个类型为
any
的变量obj
:
obj
to any other variable (except of type never
)obj
分配给任何其他变量(类型never
除外)obj
eg obj.abc.d
obj
上的任何字段,例如obj.abc.d
string
string
Code example : 代码示例:
function onlyAcceptingNumber(a: number) {}
export async function doSomething(obj: any){
// I can do this:
const a = obj.a * obj.b;
// I can also do this:
console.log(obj.a.b.c.d);
// and I can call onlyAcceptingNumber with obj
onlyAcceptingNumber(obj);
}
// but of course this could fail in runtime:
doSomething("123");
doSomething({ name: "John" });
In the example above, the doSomething
function would compile, and both calls to it would compile, but of course if we run everything, it would fail in runtime.在上面的示例中,
doSomething
function 会编译,并且对它的两次调用都会编译,但当然如果我们运行所有内容,它会在运行时失败。
To battle this, you can use eg ESLint's no-explicit-any rule, and in general only use any
as a last resort为了解决这个问题,您可以使用例如ESLint 的 no-explicit-any规则,并且通常只使用
any
作为最后的手段
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.