Typescript 类型保护适用于错误的类型,但接受未知类型

Typescript 类型保护适用于错误的类型,但接受未知类型,typescript,Typescript,我有下面的视觉测试,我只是用vs代码来视觉检查东西下面是否有红色的曲线。其目的是确保我传入的泛型类型确实约束被调用的替换类型: 它似乎允许遵守规则的作业,并正确地认识到错误类型设置了与字符串无关的内容,而不是接口定义的数字。不幸的是,它允许使用不存在的类型而不会出错 如果有帮助的话,以下是视觉效果: 这里还有一个屏幕截图,显示替代品的预期类型确实是IJob: Typescript将包含额外属性的类型视为不存在类型的类型是IJob的子类型,这就是允许调用的原因。您可以将函数参数类型视为函数需要工作

我有下面的视觉测试,我只是用vs代码来视觉检查东西下面是否有红色的曲线。其目的是确保我传入的泛型类型确实约束被调用的替换类型:

它似乎允许遵守规则的作业,并正确地认识到错误类型设置了与字符串无关的内容,而不是接口定义的数字。不幸的是,它允许使用不存在的类型而不会出错

如果有帮助的话,以下是视觉效果:

这里还有一个屏幕截图,显示替代品的预期类型确实是IJob:


Typescript将包含额外属性的类型视为不存在类型的类型是IJob的子类型,这就是允许调用的原因。您可以将函数参数类型视为函数需要工作的最小属性集,因此如果传入的参数具有更多的属性,函数就不应该关心。 Typescript确实具有将额外属性标记为错误的属性,但仅当对象文字直接指定给特定类型的变量/参数时。在本例中,您可以直接将对象文本传递给函数,也可以显式键入常量:

const nonExistantType :IJob = { // Error
    jobId: "1234",
    noCanDo: true
} 
    // OR
t.substitute({
    jobId: "1234",
    noCanDo: true // error
})
编辑

通过在typescript 2.8中使用条件类型,我们还可以检查在对象创建后是否没有额外的属性:

const wrongType = {
    jobId: "1234",
    extraneous: "foobar"
}
const nonExistantType = {
    jobId: "1234",
    noCanDo: true
}
const ruleAbidingJob = {
    jobId: "1234"
}

type NoExtraProperties<TSource, TTarget> = Exclude<keyof TSource, keyof TTarget> extends never ? true : "Extra properties detected";
function ensueNothingExtra<TSource, TTarget>(source : TSource, validation: NoExtraProperties<TSource, TTarget>) :TTarget {
    return source as any
}
const t = TypedTemplate.create<IJob>();
t.substitute(ensueNothingExtra(wrongType, true)); // this is an error
t.substitute(ensueNothingExtra(nonExistantType, true)); // this is also an error
t.substitute(ensueNothingExtra(ruleAbidingJob, true)); // this is ok

为什么会下降?如果你打算这么做,请至少留下一条评论并解释一下,这样我下次就可以学习如何改进了。我确实试图使这个问题切合实际。
const wrongType = {
    jobId: "1234",
    extraneous: "foobar"
}
const nonExistantType = {
    jobId: "1234",
    noCanDo: true
}
const ruleAbidingJob = {
    jobId: "1234"
}

type NoExtraProperties<TSource, TTarget> = Exclude<keyof TSource, keyof TTarget> extends never ? true : "Extra properties detected";
function ensueNothingExtra<TSource, TTarget>(source : TSource, validation: NoExtraProperties<TSource, TTarget>) :TTarget {
    return source as any
}
const t = TypedTemplate.create<IJob>();
t.substitute(ensueNothingExtra(wrongType, true)); // this is an error
t.substitute(ensueNothingExtra(nonExistantType, true)); // this is also an error
t.substitute(ensueNothingExtra(ruleAbidingJob, true)); // this is ok