Overloads cannot differ only by return type

江枫思渺然 提交于 2020-01-14 17:31:30

问题


I'm trying to overload a function so when using the function somewhere else, it will show the result properly that is either an array of items, void, or a single item:

getSelected(type): void;
getSelected(type): IDataItem;
getSelected(type): IDataItem[];
getSelected(type:string, one:boolean = true):any {
   if (!type) {
       return;
   }
   if (one) {
      return _.reduce<IDataItem, IDataItem>(sections[type], (current: IDataItem, p: IDataItem) => {
         return p.selected === true ? p : current;
      }, void 0);
   }

   return _.filter<IDataItem>(sections[type], (p: IDataItem):boolean => {
     return p.selected === true && p.enabled === true;
   });
}

It's giving me the error "error TS2175: Overloads cannot differ only by return type.". How can I just signal the many possibilities for the return types then?


回答1:


It is worth noting a couple of points about your original code...

You cannot call the implementation signature.

These are "overload signatures" - you can call these.

getSelected(type): void;
getSelected(type): IDataItem;
getSelected(type): IDataItem[];

The next line is the "implementation signature" - you cannot call it directly.

getSelected(type:string, one:boolean = true):any {

This means that as it stands, you cannot ever pass the one argument.

You need to type the type parameter.

Your overloads don't specify a type for the type parameter, these will have the any type - but I think you probably want to restrict this to strings. Each signature needs the annotation...

type: string

Differ based on boolean argument value, or on zero-difference

Your signature that states that if you pass true in the one argument, you'll get a single result. If you were to pass false, you'd get multiple. You can't have specialised overload signatures on boolean types, only strings - so you cannot possibly determine whether the return value will be a single item or a collection.

Also, if you can pass a string and get a void return type, or pass a string and get a IDataItem return type... the compiler cannot predict which of these you will get... so you can't use this signature.

Working overloads.

Given all these constraints, the only valid overloads would be:

class Example {
    getSelected(type: string): any;
    getSelected(type: string, one: boolean): any;
    getSelected(type: string, one: boolean = true) : any {

    }
}

Which is exactly equivalent to the simpler:

class Example {
    getSelected(type: string, one: boolean = true) : any {

    }
}

The proper solution:

Sorry it took so long to get to the answer...

class Example {
    getSelectedItem(type: string) : IDataItem {
        // return just one
    }

    getAllSelectedItems(type: string): IDataItem[] {
        // return all matches as a collection
    }
}

Have two methods. One is for obtaining a single item, one if for obtaining a collection. Handle the "empty type" case either as an Error or return an appropriate null-object to signal no result (i.e. no need for the void return type).




回答2:


Use generics in order to help the compiler to determine the right value:

getSelected<T>(type:string, one:boolean = true): T {
    // ...
}

getSelected<void>('abc');
var aDataItem = getSelected<IDataItem>('abc');
var aList = getSelected<IDataItem[]>('abc');

See also the documentation.




回答3:


If you might return anything based on the content of data passed in, and there's no common type between those possible return values, you should declare your return type to be any and force the calling code to use a type assertion.

I don't like Tarh's suggestion because it implies type safety where there is none.

Returning different types of data from a single function call is a code smell; it puts a lot of onus on the caller to understand what the relationship is between the inputs and the outputs. You'd be better off having something like getSelectedSingle, getSelectedMultiple, and getSelectedNone.



来源:https://stackoverflow.com/questions/25022331/overloads-cannot-differ-only-by-return-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!