Skip to content

Support typeof on object types #115

@SebastienGllmt

Description

@SebastienGllmt

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

if (!ts.isPropertySignature(valueDeclaration) && !ts.isMethodSignature(valueDeclaration)) {
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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions