-
Couldn't load subscription status.
- Fork 34
Description
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)) { |
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'); // falseHowever, this fails
const obj = { foo: 0 };
is<typeof obj>('foo'); // throws an exceptionSuggested 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.