Szczepan Hołyszewski
Szczepan Hołyszewski

Reputation: 3167

Declare an array type compatible with argument list of a given function?

function item(
    tag:     string,
    kind?:   string,
    name?:   string
) : string {

   return ` * ${tag}${kind ? ` [${kind}]` : ""}${name ? ` ${name}` : ""}`;
}

/*
 * Here, I need to declare the type ItemArgs that will be an array type
 * compatible with the argument list of the item() function.
 * 
 * How do I?
 */

function block(
    tag:        string,
    kind?:      string,
    name?:      string,
    ...items:   ItemArgs[]
) : string {

    // the items.map() call must compile
    return ["/**", item(tag, kind, name), ...items.map(item), " */"].join("\n");
}

// ... and this must compile too
const jsDocBlock : string = block(

    'typedef', 'Object', 'Foo',
    ['property', 'boolean', 'should'],
    ['property', undefined, 'something']
);

Upvotes: 1

Views: 39

Answers (1)

jcalz
jcalz

Reputation: 327819

For ItemArgs you can use the Parameters<F> utility type:

function block(
    tag: string,
    kind?: string,
    name?: string,
    ...items: Parameters<typeof item>[]
): string {
    return [
        "/**",
        item(tag, kind, name),
        ...items.map(args => item(...args)),
        " */"
    ].join("\n");
}

Note also that I had to change your implementation, since items.map(item) will try to call item with the wrong arguments. Each element of items is the tuple of parameters to item, which would be passed in as the first argument to item (and there are more arguments that Array.prototype.map() passes).

Anyway, this works now:

const jsDocBlock: string = block(
    'typedef', 'Object', 'Foo',
    ['property', 'boolean', 'should'],
    ['property', undefined, 'something']
);

console.log(jsDocBlock);
 // "/**
 // * typedef [Object] Foo
 // * property [boolean] should
 // * property something
 // */" 

Playground link to code

Upvotes: 2

Related Questions