Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Consider the following example. fetchItems function returns response or response body depending on passed onlyBody argument which defaults to true.

interface HttpResponse<T> {
  body: T
}

function fetchItems<T, B extends boolean>(url: string, onlyBody: B = true as B) {
  return Promise
    .resolve({body: 'some data'} as any)
    .then<B extends true ? T : HttpResponse<T>>(res => onlyBody ? res.body : res);
}

If both generic types are passed the function works as expected

const a = fetchItems<string, false>('url', false) // Promise<HttpResponse<string>>
const b = fetchItems<string, true>('url', true)   // Promise<string>
const c = fetchItems<string, true>('url')         // Promise<string>

I'd like to drop requirement of passing B type as it is redundant in relation to onlyBody parameter. But when B type is not explictly passed, ts compiler complains about it (Expected 2 type arguments but got 1).

const e = fetchItems<string>('url', false);        // would want Promise<HttpResponse<string>>
const f = fetchItems<string>('url', true)          // would want Promise<string>
const g = fetchItems<string>('url')                // would want Promise<string>

I tried to change fucntion signature into:

function fetchItems<T, B extends boolean = true>(url: string, onlyBody: B = true as B) {

but then there is an error in e example: Argument of type 'false' is not assignable to parameter of type 'true | undefined'

Is there any way to alter function signature so that e, f, g examples will work the same as a, b, c ? demo: https://stackblitz.com/edit/typescript-ydkmzk

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
1.2k views
Welcome To Ask or Share your Answers For Others

1 Answer

Function overloads can do what you need:

function fetchItems<T>(url: string, onlyBody: false): Promise<HttpResponse<T>>
function fetchItems<T>(url: string, onlyBody?: true): Promise<T>
function fetchItems<T>(url: string, onlyBody: boolean = true) {
  return Promise
    .resolve({body: 'some data'} as any)
    .then(res => onlyBody ? res.body : res);
}

Playground

Solution with conditional types does not work due to TypeScript "design limitation" described here.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...