Typescript 将“未知”缩小到具有字符串字段的对象,而不使用“任何”`

Typescript 将“未知”缩小到具有字符串字段的对象,而不使用“任何”`,typescript,Typescript,我正在尝试验证我的应用程序接收的数据。下面是一个简短的示例: function getField(data:unknown):string { if (typeof data !== 'object') { throw new Error('e1'); } if (data == null) { throw new Error('e2'); } const { field } = data; if (typeo

我正在尝试验证我的应用程序接收的数据。下面是一个简短的示例:

function getField(data:unknown):string {
    if (typeof data !== 'object') {
        throw new Error('e1');
    }

    if (data == null) {
        throw new Error('e2');
    }

    const { field } = data;

    if (typeof field !== 'string') {
        throw new Error('e3');
    }

    return field;
}

我需要从数据中提取一个字符串字段。如果数据的形状无效,代码应该抛出。问题是,上面的代码没有进行类型检查。它失败,因为“类型{}上不存在属性'field'。我知道我可以添加一些
any
,它会起作用,但我尝试在不使用
any
的情况下,以一种类型安全的方式来执行此操作。

有一个建议,允许
中的
类型保护资产化属性的存在,但它没有实现()

可以使用足够安全的类型断言(
const{field}=data as{field:unknown};
),也可以使用自定义类型保护来检查属性的存在:

function hasProp<K extends PropertyKey>(data: object, prop: K): data is Record<K, unknown> {
    return prop in data;
}
function getField(data: unknown): string {
    if (typeof data !== 'object') {
        throw new Error('e1');
    }

    if (data == null) {
        throw new Error('e2');
    }
    if (!hasProp(data, 'field')) {
        throw new Error('field does not exist');
    }
    const { field } = data;

    if (typeof field !== 'string') {
        throw new Error('e3');
    }

    return field;
}
函数hasProp(数据:对象,prop:K):数据是记录{
返回数据中的道具;
}
函数getField(数据:未知):字符串{
if(数据类型!=='object'){
抛出新错误('e1');
}
如果(数据==null){
抛出新错误('e2');
}
如果(!hasProp(数据,'字段')){
抛出新错误('字段不存在');
}
常量{field}=数据;
如果(字段类型!=='string'){
抛出新错误('e3');
}
返回字段;
}


注意由于您正在抛出异常,因此可以使用新的断言语法:

谢谢。不幸的是,这仍然依赖于程序员不犯错误(hasProp函数可以有一个空的主体,它仍然会编译)。我正在试图找到一个不需要的解决方案。@gabor hasProperty函数可以正确定义一次,并根据需要多次重用。Ts不允许您使用
中的
缩小对象范围,至少对于类型,没有其他选项可以从
对象
转换为具有其他属性的对象。