Skip to content

error issued for overloaded methods with union type args and returns  #12837

Closed
@psnider

Description

@psnider

TypeScript Version: 2.0.10, and 2.1.4

Code

type DocumentID = string
type DataType = {}
type ObjectCallback = (error:Error, result?: DataType) => void
type ArrayCallback = (error:Error, result?: DataType[]) => void
type ObjectOrArrayCallback = (error:Error, result?: DataType | DataType[]) => void

export class Read  {

    get(_id: DocumentID): DataType {return {}}

    // These functions take either a single id, and return a single object, 
    // or take an array of ids, and return an array of objects.
    read(_id: DocumentID): Promise<DataType>
    read(_id: DocumentID, done: ObjectCallback): void
    read(_ids: DocumentID[]): Promise<DataType[]> 
    read(_ids: DocumentID[], done: ArrayCallback): void
    read(_id_or_ids: DocumentID | DocumentID[], done?: ObjectOrArrayCallback): Promise<DataType> | Promise<DataType[]> | void {
        if (done) {
            if (Array.isArray(_id_or_ids)) {
                done(undefined, [{},{}])
            } else if ((typeof _id_or_ids === 'string') && (_id_or_ids.length > 0)){
                done(undefined, {})
            }
        } else {
            return this.promisify_read(_id_or_ids)   // TS2345
        }
    }

    // swapping the following two lines results in different error messages
    promisify_read(_id: DocumentID): Promise<DataType>
    promisify_read(_ids: DocumentID[]) : Promise<DataType[]> 
    promisify_read(_id_or_ids: DocumentID | DocumentID[]): Promise<DataType> | Promise<DataType[]> {
        return new Promise((resolve, reject) => {
            // TODO: resolve this typing problem
            this.read(_id_or_ids, (error, result) => {   // TS2345
                if (!error) {
                    resolve(result)
                } else {
                    reject(error)
                }
            })
        })
    }

}

Expected behavior:
I believe this code is correct, and should compile without error.

Actual behavior:
Upon compiling with: tsc --module commonjs --target es6 t.ts
the compiler outputs:

t.ts(24,40): error TS2345: Argument of type 'string | string[]' is not assignable to parameter of type 'string[]'.
  Type 'string' is not assignable to type 'string[]'.
t.ts(34,23): error TS2345: Argument of type 'string | string[]' is not assignable to parameter of type 'string[]'.
  Type 'string' is not assignable to type 'string[]'.

Also, if I switch the order of the first two declarations for promisify_read, the compiler changes its first error by reversing its selected types to:

t.ts(24,40): error TS2345: Argument of type 'string | string[]' is not assignable to parameter of type 'string'.
  Type 'string[]' is not assignable to type 'string'.

Since these are all union types, I don't expect any errors.

Have I stumbled across a bug?
I'm familiar with the rule that the first matching declaration is selected, but the first two declarations select different call forms and don't overlap with each other.

Even if the first behavior is due to incorrectly declaring my functions,
the second behavior seems just wrong.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already createdQuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions