Typescript: 对于未在所有联合成员上定义的属性,访问对象类型联合的属性失败

创建于 2016-12-10  ·  12评论  ·  资料来源: microsoft/TypeScript

TypeScript版本: 2.1.1

type A = { a: string; } 
type B = { b: string; }
type AorB = A | B;

declare const AorB: AorB;

if (AorB.a) {
    // use AorB.a
}

预期行为:
该代码编译没有错误。 即使a在工会的所有组成部分上都不存在(必需),但存在于某些工会上的事实也应允许我检查.a并使用(如果存在)。

实际行为:
Typescript抱怨:“属性a在AorB类型上不存在...属性a在类型B上不存在。”

Question

最有用的评论

我在书上找到了解决方案:

interface A { x:  number;} 
interface B { y:  string;}
function doStuff ( q: A | B ) {
  if ( 'x'  in q) {
    //  if type A...
  }
  else {
    // if type B...
  }
}

摘录自:Basarat Ali Syed。 “ TypeScript深入研究”。 苹果书。

一个对象上的属性,可以用作类型保护,并且TypeScript可以知道您使用了哪种类型。

所有12条评论

医生说:

为了使相同的代码正常工作,我们需要使用类型断言:

let pet = getSmallPet();

if ((<Fish>pet).swim) {
    (<Fish>pet).swim();
}
else {
    (<Bird>pet).fly();
}

http://www.typescriptlang.org/docs/handbook/advanced-types.html

然后在您的示例中:

if ((<A>AorB).a) {
    // use AorB.a
}

这里的问题是,因为B没有声明a属性,所以它在运行时可能具有任何可能类型的a属性(因为您可以分配一个对象,只要它具有字符串类型的b属性,就可以将具有任何属性集的对象分配给B )。 您可以使其在B明确声明a: undefined属性(从而确保B不会具有某些随机的a属性)使其工作:

type A = { a: string; } 
type B = { b: string; a: undefined }
type AorB = A | B;

declare const AorB: AorB;

if (AorB.a) {
    // Ok
}

很有道理。 脑放屁。

如果在类型B上定义a: undefined ,则在创建/传递变量时必须将其设置为undefined
为了解决这个问题,您可以将aa?: undefined ,如果忽略它,打字稿将很高兴。

如果我正确理解注释,则应该可以(但会抛出;在操场上经过测试):这是否是错误? 🤔

type LinkProps = {
    to: string;
    onClick?: undefined;
    // Link specific props:
    target: string;
}

type ButtonProps = {
    to?: undefined;
    onClick: Function;
    // Button specific props:
    disabled: boolean;
}

type ActionProps = LinkProps | ButtonProps;

const Action = (props: ActionProps) =>
    props.to ?
        'Link with target: ' + props.target // Error not on ButtonProps
    :
        'Button with disabled: ' + props.disabled; // Error: not on LinkProps

Action({
  to: 'dssd',
  target: '_blank'
});

我一点都不明白。 if ((<A>AorB).a)与if (A.a)吗,因为您要强制其返回A

如果在类型B上定义a: undefined ,则在创建/传递变量时必须将其设置为undefined
为了解决这个问题,您可以将aa?: undefined ,如果忽略它,打字稿将很高兴。

可能会更好a?: never ,现在您不能错误地分配undefined

如果您不给每个工会会员取名怎么办? (不能在没有断言类型名称的情况下进行上述类型断言,可以吗?)

type u = "str" | {prop:"val"};
function f(arg:u){return arg.prop} // TypeScript: Property 'prop' does not exist on type 'u'

有什么办法吗?

我在书上找到了解决方案:

interface A { x:  number;} 
interface B { y:  string;}
function doStuff ( q: A | B ) {
  if ( 'x'  in q) {
    //  if type A...
  }
  else {
    // if type B...
  }
}

摘录自:Basarat Ali Syed。 “ TypeScript深入研究”。 苹果书。

一个对象上的属性,可以用作类型保护,并且TypeScript可以知道您使用了哪种类型。

type ColorItemType = {
    colorId: number,
    colorName: string,
}

type NumItemType = {
    numId: number,
    numName: string
}

type ResType = {
    itemId: number,
    // 0 color 1 num
    type: number,
    itemInfo: {
        colorList: Array<ColorItemType>
        numList: Array<NumItemType>
    }
}

const request = () => {
    return [{
        itemId: 1,
        type: 0,
        itemInfo: {
            colorList: [{
                colorId: 1,
                colorName: 'blue'
            }],
            numList: []
        }
    }];
};

const dataSource: Array<ResType> = request();

const formatData = dataSource.map(dataItem => {
    const list: Array<ColorItemType | NumItemType> = dataItem.type === 1 ? dataItem.itemInfo.numList : dataItem.itemInfo.colorList;
    return list.map(listItem => {
        return {
            // An error will be reported here
            value: listItem.numId || listItem.colorId,
            label: listItem.numName || listItem.colorName
        };
    });
});

这里的问题是,因为B没有声明a属性,所以它在运行时可能具有任何可能类型的a属性(因为您可以分配一个对象,只要它具有字符串类型的b属性,就可以将具有任何属性集的对象分配给B )。 您可以使其在B明确声明a: undefined属性(从而确保B不会具有某些随机的a属性)使其工作:

type A = { a: string; } 
type B = { b: string; a: undefined }
type AorB = A | B;

declare const AorB: AorB;

if (AorB.a) {
    // Ok
}

对我不起作用07.10.2020

而且我认为TS的这种行为不好,因为它对开发人员的帮助不大。

此页面是否有帮助?
5 / 5 - 1 等级