Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
TypeScript:即使在缩小范围后也不能分配给类型的对象_Typescript - Fatal编程技术网

TypeScript:即使在缩小范围后也不能分配给类型的对象

TypeScript:即使在缩小范围后也不能分配给类型的对象,typescript,Typescript,我有一个函数,它接收一个对象并缩小它的范围,以检查它是否包含一个特定类型的属性foo,即string 在狭窄的分支中,我希望input可以分配给ObjectWithFooStringProp,但它不是出于某种原因。为什么会这样 type DictionaryLike = { [index: string]: unknown; }; type ObjectWithFooStringProp = { foo: string; }; const getObjectWithFooSt

我有一个函数,它接收一个对象并缩小它的范围,以检查它是否包含一个特定类型的属性
foo
,即
string

在狭窄的分支中,我希望
input
可以分配给
ObjectWithFooStringProp
,但它不是出于某种原因。为什么会这样

type DictionaryLike = {
    [index: string]: unknown;
};

type ObjectWithFooStringProp = {
    foo: string;
};

const getObjectWithFooStringProp = (
    input: DictionaryLike,
): ObjectWithFooStringProp | null => {
    if (typeof input.foo === 'string') {
        input.foo; // Type is `string` ✅

        // Unexpected error ❌
        // Property 'foo' is missing in type 'DictionaryLike' but required in type 'ObjectWithFooStringProp'.
        return input;

        // Workaround:
        // return { foo: input.foo };
    } else {
        return null;
    }
};

我在上面的例子中提到了一种变通方法,但是我有一个现实世界的用例,这种变通方法是不可能的,所以我很想弄清楚为什么TypeScript会以这种方式运行。

我不知道为什么这不起作用,但目前,您可以使用一个专用的类型保护程序来正确地缩小类型

type DictionaryLike = {
    [index: string]: unknown;
};

type ObjectWithFooStringProp = {
    foo: string;
};

const isObjectWithFooStringProp = (input: DictionaryLike): input is ObjectWithFooStringProp =>
  typeof input.foo === 'string'

const getObjectWithFooStringProp = (
    input: DictionaryLike,
): ObjectWithFooStringProp | null => {
    if (isObjectWithFooStringProp(input)) {
        return input;
    } else {
        return null;
    }
};

防护装置通常影响应用于整个对象的属性类型,而不是整个对象。一个值得注意的例外是对Description属性的检查确实会更改包含对象的类型的有区别的联合。但在您的护理中,我们没有歧视工会,因此检查实际上对
输入没有任何影响

唯一的解决方法是在检查后使用自定义类型保护更改
输入的类型

type DictionaryLike = {
    [index: string]: unknown;
};

type ObjectWithFooStringProp = {
    foo: string;
};
function hasStringProp<K extends string>(o: DictionaryLike, key: K) : o is Record<K, string>{
    return typeof o[key] === 'string';
}
const getObjectWithFooStringProp = (
    input: DictionaryLike,
): ObjectWithFooStringProp | null => {
    if (hasStringProp(input, 'foo')) {
        input.foo; // Type is `string` ✅

        // ok now
        return input;

        // Workaround:
        // return { foo: input.foo };
    } else {
        return null;
    }
};
type DictionaryLike={
[索引:字符串]:未知;
};
类型ObjectWithFooStringProp={
foo:string;
};
函数hasStringProp(o:DictionaryLike,key:K):o是记录{
返回o[key]=“string”的类型;
}
常量getObjectWithFooStringProp=(
输入:字典式,
):ObjectWithFooStringProp | null=>{
if(hasStringProp(输入'foo')){
input.foo;//类型为'string`✅
//好了
返回输入;
//解决方法:
//返回{foo:input.foo};
}否则{
返回null;
}
};

您可以使用
返回输入利用类型转换

type DictionaryLike={
[键:字符串]:未知
}
类型ObjectWithFooStringProp={
foo:string
}
常量getObjectWithFooStringProp=(
输入:DictionaryLike
):ObjectWithFooStringProp | null=>{
if(typeof input.foo=='string'){
input.foo//类型为'string`✅
//无误✅
返回输入
//解决方法:
//返回{foo:input.foo};
}否则{
返回空
}
}

谢谢!你知道有没有人建议在TypeScript中解决这个问题,这样对象类型本身也会改变?如果不是的话,也许我会提交一份。我故意避免在这里使用用户定义的类型保护,因为TypeScript中还有另一个设计限制:用户定义的类型保护没有任何类型检查@OliverJosephAsh并没有真正意识到这样一个提议。并不意味着一个人不存在。我知道使用类型保护缩小
对象
未知
是一个问题,但现在找不到它嘿,小世界!:-)我故意避免在这里使用用户定义的类型保护,因为TypeScript中有一个设计限制:用户定义的类型保护没有任何类型检查。然而,这并不是说这个答案是错误的,只是它不太符合我的要求。我相信这会帮助很多遇到这种情况的人。谢谢不幸的是,类型转换丢失了一些类型检查。