Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion: Type variables in function signature #32525

Closed
5 tasks done
parzh opened this issue Jul 23, 2019 · 4 comments
Closed
5 tasks done

Suggestion: Type variables in function signature #32525

parzh opened this issue Jul 23, 2019 · 4 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@parzh
Copy link

parzh commented Jul 23, 2019

Search Terms

type variable variables param parameter parameters

Suggestion

Add type variables in function signatures.

Such type variables would not be visible nor controllable by the caller of the function (sort of like private type parameters).

Use Cases

Currently (v.3.5.1) all the type parameters in the function signatures are visible by the user of this function (the one who calls it). In the following example, we have the unnecessary ability to provide typing for the second type parameter Key of the function getEntries:

interface GetEntries {
    <Obj extends object, Key extends keyof Obj = keyof Obj>(object: Obj): Array<[ Key, Obj[Key] ]>;
    // the Key type is really for private usage
    // also notice the repetitiveness of its definition
}

const getEntries: GetEntries = (object) => Object.entries(object);

interface Person {
    name: string;
    age: number;
}

declare const person: Person;

const entries1 = getEntries<Person>(person);
const entries2 = getEntries<Person, "age">(person);

entries1;
// type of entries1 is fine

entries2;
// type of entries2 is not fine,
// since the first item of each touple is not "age" , but "name" | "age"
// also, this is an unintended usage of the second type parameter

The suggested functionality is achievable though in the current version of TypeScript, but it is highly repetitive - notice the usage of keyof Obj type in the following example:

interface GetEntries {
    <Obj extends object>(object: Obj): Array<[ keyof Obj, Obj[keyof Obj] ]>;
}

Examples

The proposed functionality might introduce where .. is .. syntactical construct, more fully described as this:

{return expression} where {identifier} is {type expression} [ , {identifier} is {type expression} ]*
interface GetEntries {
    <Obj extends object>(object: Obj): Array<[ Key, Obj[Key] ]> where Key is keyof Obj;
}
interface GetEntries {
    <Obj extends object>(object: Obj): Array<[ Key, Value ]> where Key is keyof Obj, Value is Obj[Key];
}

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.
@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Jul 23, 2019
@RyanCavanaugh
Copy link
Member

This is really the intended design of type parameters - they are parametric. Any time you're trying to use a defaulted type parameter to introduce a new name, something has gone wrong.

For example, you could have written

    <Obj extends object>(object: Obj): Array<[keyof Obj, Obj[keyof Obj] ]>;

to get the desired effect without introducing a second type parameter.

It's important that callers be able to specify type parameters at all times so that they can resolve potential ambiguities

@parzh
Copy link
Author

parzh commented Jul 23, 2019

I might have been unclear in my phrasing, forgive me.

Type parameters are fine, but their purpose is to parametrize function, not introduce variables. You've pointed me to that in the comment with an example, but I've also included this exact example in the original post.

The core of the suggestion is described in the Examples section. Basically, I'm suggesting introducing completely different concept / entity

@RyanCavanaugh
Copy link
Member

Usually for a suggestion we need to start with something that can't be done, or can't be done with adequate fidelity. This doesn't really meet the bar for that.

You might also be interested in local type aliases, #23188

@parzh
Copy link
Author

parzh commented Jul 23, 2019

That really looks a lot like what I'm suggesting, thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

1 participant