Skip to content

Type assertions using Exact, Subset, Superset #28586

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

Open
ORESoftware opened this issue Nov 17, 2018 · 5 comments
Open

Type assertions using Exact, Subset, Superset #28586

ORESoftware opened this issue Nov 17, 2018 · 5 comments
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript

Comments

@ORESoftware
Copy link

ORESoftware commented Nov 17, 2018

I have suffered several times with the limitations of casting like so:

res.json(<Foo>{foo:'bar'});

the above cast/assertion will work even if the anonymous object does not have all the fields in type Foo.
For example, this question I had: https://stackoverflow.com/questions/53328459/prevent-compilation-unless-all-fields-exist

This feature request is for something like this:

res.json(Exact<Foo>{foo:'bar'});
res.json(Subset<Foo>{foo:'bar'});
res.json(Superset<Foo>{foo:'bar'});

note this is similar to the existing construct Partial, as in Partial<T>, hopefully the above are self-explanatory. I am not sure if both Subset<> and Superset<> make sense, but one of them should.

@NN---
Copy link

NN--- commented Nov 17, 2018

Exact types #12936

@weswigham
Copy link
Member

Also #26064

@weswigham weswigham added Suggestion An idea for TypeScript In Discussion Not yet reached consensus labels Nov 19, 2018
@ORESoftware
Copy link
Author

ORESoftware commented Nov 19, 2018

Looking at this again, I think both Subset<T> and Superset<T> make sense. Examples:

const v = {foo:'bar'};
const vprime = Subset<T>v;

Subset<T> acts like an assertion: the assertion is that vprime cannot have any fields that are not in T. What is returned is only what's in v, not what's in T.

next we have Superset:

const v = {foo:'bar', zoom:'zam'};
const vprime = Superset<T>v;

Superset acts like an assertion: it asserts that vprime contains all the fields in T. The type of v is returned from the assertion, not T.

@jack-williams
Copy link
Collaborator

jack-williams commented Nov 19, 2018

Does this work?

type Subset<L, R extends L> = L

type Superset<L extends R, R> = L

interface T {
    foo: 'foo';
    bar: 'bar';
}

const v: { foo: 'foo' } = {
    foo: 'foo'
};

const v2: { foo: 'foo'; bar: 'bar', baz: 'baz' } = {
    foo: 'foo', bar: 'bar', baz: 'baz'
};

const vprime1: Subset<typeof v, T> = v; // ok
const vprime2: Superset<typeof v, T> = v; // notok

const vprime2_1: Subset<typeof v2, T> = v2; // notok
const vprime2_2: Superset<typeof v2, T> = v2; // ok

@ORESoftware
Copy link
Author

ORESoftware commented Nov 20, 2018

@jack-williams probably, except I am looking to use it with an anonymous object, like so:

type T = ...

doMyThang((err, val) => {
    res.json(<T>val.x);
});

it needs to be an assertion like that...AKA doing it this way instead kinda takes all my joy away:

type T = ...
doMyThang((err, val) => {
   const x : T = val.x;    ///  << superfluous code that I don't want to write or see
    res.json(x);
});

Doing it with anonymous objects is the higher level goal I think.

yunuseon added a commit to yunuseon/TypeScript that referenced this issue Jul 15, 2019
The subset type will allow creating true subsets of models to model
things like partial DTOs and the like.

Resolves microsoft#12936 (and microsoft#28586 to some extent)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

4 participants