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

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

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

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

代码

  1. interface ReportState {
  2. reportDefinition: {
  3. [key: number]: ReportDetails;
  4. };
  5. }
  6. interface ReportDetails {
  7. requiredNumber: number;
  8. columnWidths?: number[];
  9. }
  10. export const Report: (state: ReportState, action: any) => ReportState = (
  11. state,
  12. action
  13. ) => { // See note below about this line
  14. switch (action.type) {
  15. case "TYPE0": {
  16. const { reportDef, sequenceId } = action.payload;
  17. return {
  18. ...state,
  19. reportDefinition: {
  20. ...state.reportDefinition,
  21. [sequenceId]: {
  22. ...reportDef,
  23. selectedElements: ["0x0"],
  24. },
  25. },
  26. };
  27. }
  28. case "TYPE1": {
  29. return {
  30. ...state,
  31. reportDefinition: {
  32. ...state.reportDefinition,
  33. [action.payload.sequenceId]: {
  34. // requiredNumber is missing here. This should be an error.
  35. columnWidths: action.payload.columnWidths,
  36. },
  37. },
  38. };
  39. }
  40. default:
  41. return state;
  42. }
  43. };

预期行为:

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

实际行为:

编译成功且无错误。

  • 好奇心1:*

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

  • 好奇心2:*

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

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

vkc1a9a2

vkc1a9a21#

关于修复的想法?减少:

  1. interface ReportState {
  2. reportDefinition: {
  3. [key: number]: {
  4. a: number
  5. };
  6. };
  7. }
  8. const fn: () => ReportState = () => {
  9. if (Math.random() > 0.5) {
  10. return null as any as { reportDefinition: { [key: number]: any } };
  11. } else {
  12. return {
  13. reportDefinition: {
  14. // 'a' is missing, but no error
  15. 0: { }
  16. }
  17. }
  18. }
  19. }
展开查看全部
kcrjzv8t

kcrjzv8t2#

更简单的复现:

  1. const fn2: () => number = () => {
  2. if (!!true) {
  3. return 5 as any;
  4. }
  5. else {
  6. return 'abc';
  7. }
  8. }

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

f45qwnt8

f45qwnt83#

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

wpcxdonn

wpcxdonn4#

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

  1. // --------------- RyanCavanaugh example:
  2. interface ReportState {
  3. reportDefinition: {
  4. [key: number]: {
  5. a: number
  6. };
  7. };
  8. }
  9. declare const returnA: { reportDefinition: { [key: number]: any } };
  10. const returnB = { reportDefinition: { 0: {} } };
  11. declare const returnUnion1: typeof returnA | typeof returnB;
  12. const return1Assigned: ReportState = returnUnion1; // <-- error here
  13. // -------------- ahejlsberg example:
  14. const returnC = 5 as any;
  15. const returnD = 'abc';
  16. declare const returnUnion2: typeof returnC | typeof returnD;
  17. const return2Assigned: number = returnUnion2; // <-- no error here

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

展开查看全部

相关问题