admin管理员组

文章数量:1315338

I have a method that returns different type based on option key value.

class Test {
  getData(options: { obj: true }): Object;
  getData(options: { obj: false }): any[];
  getData(): any[];
  getData(options = { obj: false }): Object | any[] {
    if (options.obj) {
      return {};
    } else {
      return [];
    }
  }
}

When passing the obj as true, I'm returning object otherwise array. That works fine.

const instance = new Test();
const result = instance.getData({ obj: true }); // inffered as array
const result2 = instance.getData(); // inffered as object

The problem is when I need to use dynamic value it throws an error:

type boolean is not assignable to type false

function getResult(obj: boolean = false ) {
  return instance.getData({ obj });
}

What is the problem?

I have a method that returns different type based on option key value.

class Test {
  getData(options: { obj: true }): Object;
  getData(options: { obj: false }): any[];
  getData(): any[];
  getData(options = { obj: false }): Object | any[] {
    if (options.obj) {
      return {};
    } else {
      return [];
    }
  }
}

When passing the obj as true, I'm returning object otherwise array. That works fine.

const instance = new Test();
const result = instance.getData({ obj: true }); // inffered as array
const result2 = instance.getData(); // inffered as object

The problem is when I need to use dynamic value it throws an error:

type boolean is not assignable to type false

function getResult(obj: boolean = false ) {
  return instance.getData({ obj });
}

What is the problem?

Share Improve this question asked Jun 19, 2018 at 16:02 undefinedundefined 6,88413 gold badges53 silver badges101 bronze badges 0
Add a ment  | 

2 Answers 2

Reset to default 7

Since the type of { obj } is only known as { obj: boolean } at pile time, the piler can't know to pick any of the overloads, you have to explicitly supply an overload that takes { obj: boolean } (since the implementation signature does not count as a public signature for the function), the piler will not do any magic in this case:

class Test {
    getData(options: { obj: true }): Object;
    getData(options: { obj: false }): any[];
    getData(options: { obj: boolean }): Object | any[];
    getData(): any[];
    // This signature is the implementation and is not conidered when resolving the method 
    getData(options = { obj: false }): Object | any[] {
        if (options.obj) {
            return {};
        } else {
            return [];
        }
    }
} 

Edit

You can also use conditional types in the method signature and this will keep the number of signatures lower:

class Test {
    getData<T extends boolean>(options: { obj: T }): T extends true ? Object : any[];
    getData(): any[];
    // This signature is the implementation and is not conidered when resolving the method 
    getData(options = { obj: false }): Object | any[] {
        if (options.obj) {
            return {};
        } else {
            return [];
        }
    }
}


const instance = new Test();
const result = instance.getData({ obj: true }); // inffered as array
const result2 = instance.getData(); // inffered as object

function getResult(obj: boolean = false) {
    return instance.getData({ obj }); // inferred as Object|any[]
}

Since type boolean = true | false and conditional types distribute over unions, T extends true ? Object : any[]; will be Object|any[] when T is boolean. When T is true, the return will be Object and when T is false, the return will be any all as expected

You cannot overload methods in TypeScript like you do in C#, for example. You need to bine types, like this:

class Test {

  getData(options: {obj: boolean} = { obj: false }): Object | any[]  {
   if (options.obj) {
        return {};
      } else {
        return [];
      }
   }
}

When you redeclare the function with the same name several times, you will just get the last one as the final definition, in runtime.

本文标签: javascriptTypescript overloading type boolean is not assignable to type falseStack Overflow