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

Allow static assertions #18523

Closed
dead-claudia opened this issue Sep 16, 2017 · 5 comments
Closed

Allow static assertions #18523

dead-claudia opened this issue Sep 16, 2017 · 5 comments
Labels
Duplicate An existing issue was already created

Comments

@dead-claudia
Copy link

Currently, there's only a few ways to statically assert a type (and error if it fails), and they're extremely hacky and limited to effectively value is Type:

// 1.
const expectType: T = something;
const expectUnreachable: never = something;

// 2.
function expectType<T>(value: T): void {}
expectType<T>(something);
expectType<never>(something); // unreachable

My proposal:

// Type-level, error iff `Foo` is not assignable to `Bar`
assert Foo extends Bar;

// Type level, error if it is reachable
assert never;

// Value-level sugar
assert foo is Foo;
assert typeof foo extends Bar; // equivalent

These are all statements, and none of these would cause an emit. (You could include comments, though.)

This would be equally useful in:

  1. Asserting a value's type statically without requiring an emit.
  2. Asserting the unreachability of a code path
  3. Verifying a complex data structure (like ESTree's) to avoid bugs.
  4. Giving first-class support for testing external definition files like those on DefinitelyTyped.

And in case you're wondering, I drew quite a bit of inspiration from C/C++.


I know this general idea has been brought up multiple before, but there oddly was no dupe I could immediately find...

@yortus
Copy link
Contributor

yortus commented Sep 16, 2017

Looks pretty much the same as #10421, but the syntax proposed there uses assume instead of assert.

@gcnew
Copy link
Contributor

gcnew commented Sep 16, 2017

I've been using HasType for that purpose:

type HasType<T, Q extends T> = Q;

Example:

type Just<T> = { tag: 'just',   value: T }
type Nothing = { tag: 'nothing' }

type Maybe<T> = Just<T> | Nothing

function f<T>(x: Maybe<T>) {
    switch (x.tag) {
        case 'just': {
            type StaticAssert = HasType<Just<T>, typeof x>
            return 0;
        }

        case 'nothing': {
            type StaticAssert = HasType<Nothing, typeof x>
            return 1;
        }

        default: {
            type StaticAssert = HasType<never, typeof x>

            // false positive, however it's usually not a problem
            type FalsePositive = HasType<number, typeof x>

            throw 'never?';
        }
    }
}

@DanielRosenwasser DanielRosenwasser added In Discussion Not yet reached consensus Suggestion An idea for TypeScript labels Sep 16, 2017
@dead-claudia
Copy link
Author

@yortus That issue involves a type-casting component (it calls itself type narrowing, but it's not really). Mine is simply a type assertion, and a relatively dumb one at that. In particular, these two would be technically equivalent mod emit (for mine):

// Proposed
assert Foo extends Bar;
assert foo is Bar;

// Equivalent
const _unused1: Bar = 0 as any as Foo;
const _unused2: Bar = 0 as any as typeof foo;

@RyanCavanaugh RyanCavanaugh added Duplicate An existing issue was already created and removed In Discussion Not yet reached consensus Suggestion An idea for TypeScript labels Jan 30, 2018
@RyanCavanaugh
Copy link
Member

Tracking at #10421

@RyanCavanaugh
Copy link
Member

To be clear we're interested in both the "function call with type-asserting side effects" and "statement-form type assertion that affects the rest of the block" forms.

@microsoft microsoft locked and limited conversation to collaborators Jul 3, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

5 participants