TypeScript 上下文类型检查未能在等号左边的函数返回类型处抛出错误,

ozxc1zmp  于 2个月前  发布在  TypeScript
关注(0)|答案(4)|浏览(41)

TypeScript 版本: 在 3.7.4 和 4.0.0-dev.20200601 上,我得到了相同的行为。
搜索词:

左侧
右侧
上下文类型检查
类型推断

代码

interface ReportState {
  reportDefinition: {
    [key: number]: ReportDetails;
  };
}

interface ReportDetails {
  requiredNumber: number;
  columnWidths?: number[];
}

export const Report: (state: ReportState, action: any) => ReportState = (
  state,
  action
) => { // See note below about this line
  switch (action.type) {
    case "TYPE0": {
      const { reportDef, sequenceId } = action.payload;
      return {
        ...state,
        reportDefinition: {
          ...state.reportDefinition,
          [sequenceId]: {
            ...reportDef,
            selectedElements: ["0x0"],
          },
        },
      };
    }

    case "TYPE1": {
      return {
        ...state,
        reportDefinition: {
          ...state.reportDefinition,
          [action.payload.sequenceId]: {
            // requiredNumber is missing here. This should be an error.
            columnWidths: action.payload.columnWidths,
          },
        },
      };
    }

    default:
      return state;
  }
};

预期行为:

应该出现错误,因为缺少第二个返回语句中的 requiredNumber。

实际行为:

编译成功且无错误。

  • 好奇心1:*

如果你在 = 的右侧添加返回类型,例如将
) => {
更改为
): ReportState => {
,它会正确地找到错误。这不应该有必要,因为返回类型已经在 = 的左侧指定了。

  • 好奇心2:*

如果你删除第一个 case 块,它会正确地找到错误(错误在第二个 case 块中)。

** playground 链接:**点击这里
相关问题:

vkc1a9a2

vkc1a9a21#

关于修复的想法?减少:

interface ReportState {
    reportDefinition: {
        [key: number]: {
            a: number
        };
    };
}

const fn: () => ReportState = () => {
    if (Math.random() > 0.5) {
        return null as any as { reportDefinition: { [key: number]: any } };
    } else {
        return {
            reportDefinition: {
                // 'a' is missing, but no error
                0: { }
            }
        }
    }
}
kcrjzv8t

kcrjzv8t2#

更简单的复现:

const fn2: () => number = () => {
    if (!!true) {
        return 5 as any;
    }
    else {
        return 'abc';
    }
}

这个技术上是按预期工作的。返回类型是每个 return 表达式类型的联合体。由于其中一个是 any ,所以联合体减少为 any ,没有报告错误。

f45qwnt8

f45qwnt83#

原始示例中没有明确将 any 作为返回类型。第一个返回类型是否被解释为 any?

wpcxdonn

wpcxdonn4#

嗯,@ahejlsberg ,我不确定我是否理解你的示例和@RyanCavanaugh的示例是等价的?如果你移除函数并只看类型的可分配性,而不考虑任何返回类型推断的内容,那么Ryan的示例会产生一个错误(正如我所预期的),而你的示例不会(同样正如我所预期的):

// --------------- RyanCavanaugh example:

interface ReportState {
    reportDefinition: {
        [key: number]: {
            a: number
        };
    };
}

declare const returnA: { reportDefinition: { [key: number]: any } };

const returnB = { reportDefinition: { 0: {} } };

declare const returnUnion1: typeof returnA | typeof returnB;

const return1Assigned: ReportState = returnUnion1; // <-- error here

// -------------- ahejlsberg example:

const returnC = 5 as any;

const returnD = 'abc';

declare const returnUnion2: typeof returnC | typeof returnD;

const return2Assigned: number = returnUnion2; // <-- no error here

Playground链接
鉴于在“Ryan示例”中存在赋值错误,我原本预计在函数返回上下文中也会有相同的情况。然而,在你的例子中,尽管行为在某种程度上可能不是理想的,但我可以理解返回类型联合的原因,并且最终归结为any,并且不会产生错误。

相关问题