使用结构类型和变量重新分配来绕过 "named parameters" 函数调用的类型检查
Using structural typing and variable reassignment to bypass type checking on a function call with "named parameters"
function myFunc({ param1 }: {
param1: number;
}) {
// param1 is marked as mandatory in the definition, but we can bypass that
}
const mismatchedFunc: ({}) => void = myFunc;
mismatchedFunc({}); // No compile-time error
我猜测这种行为的原因源于 TypeScript 的结构类型性质,因为 { param1: number }
在结构上 "fits into" {}
.
然而,这不是不良行为(在这种特殊情况下,或 class 的情况下),因为它在很大程度上绕过了 TypeScript 提供的类型检查吗?
是否应将其作为错误提交?
编辑 1
正如@shusson 指出的那样,这种行为(截至 v2.x)是预期的(由于权衡),即使它是不可取的。
有关问题根源的最相关讨论,请参阅 this GitHub issue and a follow-up proposal 以尝试解决它。
这里发生了两件事:
- structural typing
The basic rule for TypeScript’s structural type system is that x is compatible with y if y has at least the same members as x.
- bivariant function parameters
When comparing the types of function parameters, assignment succeeds if either the source parameter is assignable to the target parameter, or vice versa
示例:
type t1 = { param1: number };
type t2 = { };
let f1 = (a: t1) => {};
let f2: (a: t2) => void = f1; // bivariant assignment
let x: t1 = { param1: 1 };
let y: t2 = {};
y = x; // because of this, f1 is assignable to f2 through bivariant assignment
x = y; // compile error
f1(x);
f1(y); // compile error
f2(x);
f2(y);
function myFunc({ param1 }: {
param1: number;
}) {
// param1 is marked as mandatory in the definition, but we can bypass that
}
const mismatchedFunc: ({}) => void = myFunc;
mismatchedFunc({}); // No compile-time error
我猜测这种行为的原因源于 TypeScript 的结构类型性质,因为 { param1: number }
在结构上 "fits into" {}
.
然而,这不是不良行为(在这种特殊情况下,或 class 的情况下),因为它在很大程度上绕过了 TypeScript 提供的类型检查吗?
是否应将其作为错误提交?
编辑 1
正如@shusson 指出的那样,这种行为(截至 v2.x)是预期的(由于权衡),即使它是不可取的。
有关问题根源的最相关讨论,请参阅 this GitHub issue and a follow-up proposal 以尝试解决它。
这里发生了两件事:
- structural typing
The basic rule for TypeScript’s structural type system is that x is compatible with y if y has at least the same members as x.
- bivariant function parameters
When comparing the types of function parameters, assignment succeeds if either the source parameter is assignable to the target parameter, or vice versa
示例:
type t1 = { param1: number };
type t2 = { };
let f1 = (a: t1) => {};
let f2: (a: t2) => void = f1; // bivariant assignment
let x: t1 = { param1: 1 };
let y: t2 = {};
y = x; // because of this, f1 is assignable to f2 through bivariant assignment
x = y; // compile error
f1(x);
f1(y); // compile error
f2(x);
f2(y);