确保功能签名类型取决于其他参数的值

时间:2019-08-16 15:04:29

标签: typescript

我正在尝试编写一个函数来验证属性是否具有泛型类型并返回其值。

// tslint:disable-next-line no-any -> must be any, or typescript can't infer the return value
function ensureProperty<T>(obj: object, propertyName: string, guard: (obj: any | undefined) => obj is T): T {
    const val = obj[propertyName];
    if (!guard(val)) {
        throw new Error(propertyName);
    }
    return val;
}

哪种方法效果很好,但是我想知道是否有一种方法可以告诉打字稿对象obj应该是具有指定名称属性的类型。

const obj = { example: ""};
ensureProperty(obj, "notexisting", Guard.isString); // this should result in a type error
ensureProperty(obj, "example", Guard.isString); // this should work

我在想类似的事情:(我知道这行不通,我只是在想这可能会澄清我的意图...)

function ensureProperty<T>(obj: {[key == propertyName]: T|undefined}, propertyName: string, ...

但是,恐怕没有这样的语言构造了吗?

1 个答案:

答案 0 :(得分:1)

您可以做类似的事情

function ensureProperty<T, K>(obj: K, propertyName: keyof K, guard: (obj: any | undefined) => obj is T): T {
    const val = obj[propertyName];
    if (!guard(val)) {
        throw new Error(propertyName.toString());
    }
    return val;
}

结果

const obj = { example: ""};
ensureProperty(obj, "notexisting", Guard.isString); // Argument of type '"notexisting"' is not assignable to parameter of type '"example"'.
ensureProperty(obj, "example", Guard.isString); // OK

请注意,现在propertyName无法直接传递给Error构造函数,因此我们必须先将其转换为字符串。