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

Add anonymous type declarations #17640

Closed
SamPruden opened this issue Aug 6, 2017 · 8 comments
Closed

Add anonymous type declarations #17640

SamPruden opened this issue Aug 6, 2017 · 8 comments
Labels
Duplicate An existing issue was already created Suggestion An idea for TypeScript

Comments

@SamPruden
Copy link

SamPruden commented Aug 6, 2017

This issue is branching out of discussion in #17636, and largely intended to support that feature.

In the language as it stands today, this would look something like

type A<T> = ( type <U> = {value: U}; )<T>;

This is really not very useful. However, #17636 proposes type declaration overloading, which would allow type switching and filtering within the type system. Anonymous type declarations would allow for inline type switches, reducing the need for global type declarations, and support a further proposal that would alleviate the need for #6606, see #17641.

With type declaration overloads, these anonymous type declarations may look something like

type Foo<T> = {
    value: (
        type <U extends number> = {aNumber: number};
        type <U> = {aDefault: U};
    )<T>
};

For details of how the overloading works, see #17636.

Anonymous type declarations (ATDs?) should probably be allowed in interfaces too, such that Foo<T> above could be an interface.

@SimonMeskens
Copy link

I'm hugely in favor of this proposal. As noted in #17636, I would only allow overloading as part of this proposal, not on its own, to alleviate concerns with ordering and declaration merging.

@masaeedu
Copy link
Contributor

masaeedu commented Aug 7, 2017

More generally, we need support for generic values; i.e. the ability to add arbitrary levels of type abstraction to any type expression. If I have the type Foo<T>, I should be able to declare const x: <A> Foo<A>, just as in other languages you can do forall a. Foo a, or forall a. forall b c. Foo a b c. Currently this is possible in a special cased form for function values, i.e. we can write const x: <T>(t: T) => <U>(u: U) => Foo<T, U>, but not for any other kinds of values. I've tried to lay out a motivating example for this in #17574

@SamPruden
Copy link
Author

@masaeedu

That's a really interesting point, and to be honest I'm not nearly experienced enough with the right languages to be able to process it super easily. Once I've got my head around it I'll have a think about how that could play nicely with the rest of the little network of suggestions that have fallen out of #17636.

Is that suggestion something you can see fitting in nicely alongside these others? Does it clash in any way, or make anything else redundant? Your wording posting here indicates that maybe you think #17574 would cover the requirement for this?

@masaeedu
Copy link
Contributor

masaeedu commented Aug 7, 2017

@TheOtherSamP No, the things you are suggesting (as far as I understand at least) seem like they would solve lots of my problems. I'm just going around trying to reference "prior art" concepts that are similar from other languages, so people involved can study those to get a feel for the tradeoffs involved and perhaps pick simpler, more general designs.

@masaeedu
Copy link
Contributor

masaeedu commented Aug 7, 2017

To put it another way, if we end up implementing this instead of #17574, I would still be able to encode "polymorphic values" using this feature. The two requests are more or less equivalent in power, just different in syntax.

However it subjectively "feels" more natural to me to simply express this feature as a generalization of generic functions. Just as we say "for all types T, a function that embeds T in an array" is <T> (x: T) => T[], we should be able to say "for all types T, a Fooer of Ts" is <T> Fooer<T>, and "a function that returns, for all types T, a fooer of Ts" is () => <T> Foo<T>. Syntax negotiable.

@SamPruden
Copy link
Author

@masaeedu

That's interesting. As someone who doesn't have a background in type theory or the relatively obscure (well, ish) type-heavy functional languages like Haskell, that's pretty unintuitive for me. It may of course be really simple and easy once you get to play with a working example for two minutes. I suspect that I represent the majority of TypeScript users in that respect though.

Would you be able to provide a couple of little examples of side-by-side comparisons of the two approaches to some simple problems so we can do a more direct comparison?

@KiaraGrouwstra
Copy link
Contributor

Turns out internally these already exist, more related snippets in that checker.ts too big for Github search to check.

@mhegazy mhegazy added the Suggestion An idea for TypeScript label Aug 22, 2017
@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Aug 15, 2018
@RyanCavanaugh
Copy link
Member

We now have conditional types, which seem to solve the use cases presented here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

6 participants