woutervh- / typescript-is

MIT License
959 stars 35 forks source link

Support typeof on object types #115

Open SebastienGllmt opened 2 years ago

SebastienGllmt commented 2 years ago

Description

Currently typescript-is fails with Failed to transform node when trying to index type using a generic type

This happens on latest master (0.19.0)

Issue reproduction

Both of these tests will fail


export const Status = {
    enable: 'enable',
    disable: 'disable'
} as const;

type StatusObject<Key extends 'enable' | 'disable'> = {
    status: (typeof Status)[Key];
};

describe('is', () => {
    describe('Accessing generic member of a type', () => {
        it('should return true for the right member', () => {
            assert.deepStrictEqual(is<StatusObject<'enable'>>({ status: Status.enable }), true);
        });
        it('should return false for the wrong member', () => {
            assert.deepStrictEqual(is<StatusObject<'enable'>>({ status: Status.disable }), false);
        });
    });
});

Investigation

Specific issue in this case

Currently, the code will throw on https://github.com/woutervh-/typescript-is/blob/0dbefd0d7f7e455ecd018673868b7bf7785c1296/src/transform-inline/visitor-utils.ts#L78 because the type of the node is TypeParameter which doesn't match either case.

It looks like the cause of this issue is that TypeParameter contains both a valueDeclaration AND a type member

SymbolObject {
    ...
    valueDeclaration: NodeObject {
      ...
    },
    type: TypeObject {
      ...
    },
    target: SymbolObject {
      ...
    }
  }

General case

In fact, it looks like this case affects any usage of typeof. For example, the following code works just fine:

type Foo = { foo: 0 };
is<Foo>('foo'); // false

However, this fails

const obj = { foo: 0 };
is<typeof obj>('foo'); // throws an exception

Suggested fix

I think the fix is as simple as switching the priority of the condition here: check type first and THEN check valueDeclaration. This passes all existing tests and also fixes the two typeof issues I mentioned above.

Related issues

Possible #59 #97 #103