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

Extends but Isn't #42177

Closed
RGFTheCoder opened this issue Jan 2, 2021 · 2 comments
Closed

Extends but Isn't #42177

RGFTheCoder opened this issue Jan 2, 2021 · 2 comments

Comments

@RGFTheCoder
Copy link

RGFTheCoder commented Jan 2, 2021

Suggestion

πŸ” Search Terms

Extends but isn't
extends parent but not parent

βœ… Viability 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, new syntax sugar for JS, etc.)
  • [*] This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

I suggest adding an operator (?) similar to extends which "extends but isn't". This would allow generics that define a specific string type "cm" or "mm". The actual operator name (referred to as extendsisnt in the example) is up for debate as I can't decide what it could be used for.

πŸ“ƒ Motivating Example

interface M<T extendsisnt string> extends number {}; // To keep types after function call rather than aliasing

function add<T extendsisnt string>(a: M<T>, b: M<T>): M<T> {
    return (a as number)  + (b as number);
}

let a: M<"cm"> = 5;
let b: M<"cm"> = 3;
let c: M<"s"> = 4;

add(a, b); // No error. Equivalent to:
add<"cm">(a, b);

add(a, c); // Should Error. "cm" != "s" and `T` can't be `string`
// ^ This would be equivalent to `add<string>(a, c)` if `extends` was used in the function definition and would be allowed. 

It is up for debate if aliases would count as "isn't"

interface a {
    b: number;
};
interface b extends a {};
type c = a;

function test<T extendsisnt a>(param: T): void {}

let a: a; // Base
let b: b; // Extends
let c: c; // Alias
test(a) // Errors since a is `a`
test(b) // No Error since b `extends` a and isn't `a`
test(c) // ?? Possible error depending on if extendsisnt counts aliases as the same or different

πŸ’» Use Cases

Allowing ONLY subclasses/extensions of classes but not the classes themselves.

@MartinJohns
Copy link
Contributor

Duplicate of #202. You're also interested in #364.

@RGFTheCoder
Copy link
Author

RGFTheCoder commented Jan 2, 2021

How would you implement the measures example using #202?
The goal would be to allow type parameters that are nominal children of the string superclass. This would still require a extendsisnt would it not?

Edit: NVM. It seems like it might work depending on how the proposal works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants