【问题标题】:typescript type check error does not shown when not all property matches并非所有属性都匹配时,不显示打字稿类型检查错误
【发布时间】:2026-01-04 22:15:01
【问题描述】:

如果接口 A 和接口 B 只有一个公共属性,则不会显示像这样的 typescript 编译器错误。为什么?

Type '{ a: string; c: number; }' is not assignable to type 'A'.
  Object literal may only specify known properties, and 'c' does not exist in type 'A'. 

此错误不仅应显示在 object literal 中,还应显示在 interface 中。

  1. 谁能回答以下问题? (第一季度、第二季度、第三季度)
  2. 有没有办法检查更严格?
interface A {
    a?: string;
    b?: number;
}

interface B {
    a?: string;
    c?: number;
}

interface C {
    x?: string;
}

const f = (args: A[]) => {
    console.log(args);
};

// (1) error: type check 
const x = () => {
    f([{ a: 'a', c: 1 }]);
};

// (2) no error. Q1. what is the difference between (1) and (2)?
const y = () => {
    const args = [
        { a: 'a', c: 1 }
    ]
    f(args);
};

// (3) error: A and C have no common property
const z = () => {
    f([] as C[]);
};

// (4) no error. [Q2] what is the difference between (3) and (4)?
const w = () => {
    f([] as B[]);
};

// (5) error: A and C have no common property
const u = () => {
    f([{ x: 1 } as C]);
};

// (6) no error. [Q3] what is the difference between (5) and (6)?
const v = () => {
    f([{ c: 1 } as B]);
};

Playground Link

【问题讨论】:

标签: typescript compiler-errors


【解决方案1】:

(1)和(2)有什么区别?

// (1) error: type check 
const x = () => {
    f([{ a: 'a', c: 1 }]);
};

// (2) no error. 
const y = () => {
    const args = [
        { a: 'a', c: 1 }
    ]
    f(args);
};

在 (1) 中,为您在 f 中创建为数组参数项的对象字面量提供了显式类型 A。因此excess property checks(开发人员的一个简洁的安全功能!)启动,它不允许像c 这样的附加属性。 ==> 错误

在 (2) 中,const args 的类型由编译器推断(无显式类型),此处没有多余的属性检查。 [{ a: 'a', c: 1 }] structurally 适合 f 函数参数 A[],因为编译器从给定的 A 中识别出至少一个属性 a 来自给定的 args。并且A 中的属性b 是可选的/可以是undefinedTS docs example 带有“公共属性”)==> 编译

修复 (2) - 注释显式类型:

// now errors
const args: A[] = [
        { a: 'a', c: 1 }
]

(3)和(4)有什么区别?

// (3) error: A and C have no common property
const z = () => {
    f([] as C[]);
};

// (4) no error. 
const w = () => {
    f([] as B[]);
};

使用 (3) 中的类型断言,您说编译器应处理 [] as C[]C 不可分配/没有A 的子类型,因此C[] 不能传递给期望A[] 的东西。 B 可以分配给A,这样就可以了! (4).


(5)和(6)有什么区别?

// (5) error: A and C have no common property
const u = () => {
    f([{ x: 1 } as C]);
};

// (6) no error. 
const v = () => {
    f([{ c: 1 } as B]);
};

(5) 与上面类似:C 不适合 A。 (6) 更有趣:您将{ c: 1 } 强制为B,这是有效的。而且这种类型的断言破坏了过多的属性检查,因此该论点再次符合结构。

鉴于您在 (4) 和 (6) 中的类型断言,尚不清楚/取决于上下文,我们如何“使其更严格”。也许完全忽略断言?

希望,除了 mentioned question 之外,这会有所帮助。

【讨论】:

  • 感谢您的精彩回答!! B is assignable to A 对我来说有点奇怪……
  • “奇怪”到什么程度? :-) 老实说,我的第一反应是相似的……但从结构类型的角度来看,这是有道理的。由于bA 中是可选的,所以我们总是可以使用类型B 来代替A。在这种情况下,唯一可以帮助我们的是多余的属性检查。
最近更新 更多