TypeScript根据接口检查推断的类型

时间:2020-08-09 20:25:53

标签: typescript

是否可以在编译时确保推断出的类型与另一个接口匹配而又不丢失推断出的类型?

对这个简单的界面和一个实现它的对象说:

interface Person {
  name: string;
}

const bob = {
  name: "Bob"
}

type Bob = typeof bob;

我想保留比Bob更具体的推断类型Person,但我还要确保它与Person匹配。

const bob: Bob = {  // this kills the implicit type
  name: "bob"
}

----

const bob = {}  // but I want this to fail, because `name` is missing

----

const bob = {
  name: "Bob",
  age: 30, // I want this to fail too, because it doesn't correspond to `Person`
}

2 个答案:

答案 0 :(得分:2)

我认为可以说“打字稿方式”是扩展接口。

interface Person {
  name: string;
}

interface Bob extends Person {
  name: "Bob"
}

诚然,它在语义上并不相同,但我认为它可以实现您所寻找的东西。

interface Person {
    name: string;
}

interface Bob extends Person {
    name: "Bob"
}

function test()
{
    const bob: Bob = {  // works
        name: "Bob"
    }

    const bob2: Bob = {}  // Not allowed

    const bob3: Bob = {
        name: "Bob",
        age: 30, // Not allowed
    }
}

答案 1 :(得分:0)

通常,这是通过使用功能来管理的。例如,您可以将使用bob的代码重构为接受Person类型参数的函数,而不是仅声明类型的无操作。如果您希望他们“超越一个人”,则可以使用<T extends Person>(p: T) => void

这样的签名

话虽如此,但它可以完成,尽管它会生成真正的代码,但对任何事情都无济于事。

在此示例中,一个asserter函数接受一个泛型类型参数,并生成一个带有.assert方法的对象,该方法将传递您所使用的对象的类型,同时还要检查它的扩展性预期的类型。

interface Person {
  name: string;
}

function asserter<Intended>() {
    return {
        assert: function<T>(input: T extends Intended ? T : never): T {
            return input as any
        }
    }
}

// the extra "water" will be accepted, but this won't compile if "name" is missing
const bob = asserter<Person>().assert({ name: '', water: ''})