-
-
Notifications
You must be signed in to change notification settings - Fork 67
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
Add Jest like API #168
base: main
Are you sure you want to change the base?
Add Jest like API #168
Conversation
Add type Test<T extends number> = T;
// Pass
assertType<Test<string>>().toThrowError();
assertType<Test<string>>().toThrowError(2344);
assertType<Test<string>>().toThrowError('does not satisfy the constraint');
assertType<Test<string>>().toThrowError(/^Type 'string'/);
// Fail
assertType<Test<number>>().toThrowError();
assertType<Test<string>>().toThrowError(2244);
assertType<Test<string>>().toThrowError('poes not satisfy the constraint');
assertType<Test<string>>().toThrowError(/Type 'string'$/); |
I'm personally not a big fan of the Jest API, but I'll leave that decision to Sam. |
How does the problem disappear by design? If it fixes that issue, that is a big benefit of this PR. |
I think it does! (since the Would this be a replacement for the existing API? Seems confusing to have two very different ways of using tsd, one of which can tell you everything's ok when it's not. I ask partly because it might be nice to align APIs with expect-type here too - Since there are some users of each it could be nice to give them the same API (some people might care more about CLI error messages who'd go for |
That's right. The thing with the current design is that we share the same parameter to test two potentially different types and due to the nature of TS generic inference this can produce unexpected results with optional parameter. As we provide the expected type it will be propagated to parameters that are not defined in the target type. declare const inferrable: <T = 'SomeDefaultValue'>() => T
function expectType<Expected>(expected: Expected): void {}
expectType<number>(inferrable()); // 'T' is inferred from 'Expected' => number
expectType(inferrable<number>()); // 'Expected' is inferred from 'T' => number
expectType(inferrable()); // Since no parameter was provided 'Expected' is inferred from 'T' default value => 'SomeDefaultValue' By splitting the expected type and the actual type and ensuring that the user never produces a generic and an argument at the same time the bug no longer occurs. assertType(foo).assignableTo(bar);
assertType(foo).assignableTo<Bar>();
assertType<Foo>().assignableTo(bar);
assertType<Foo>().assignableTo<Bar>();
assertType<Foo>(bar).assignableTo<Bar>(); // Error: Do not provide a generic type and an argument value at the same time.
assertType<Foo>().assignableTo(); // Error: A generic type or an argument value is required.
This is a very good question. I think they can coexist without any problem for a while to allow a smooth transition. But that's a decision for @SamVerschueren to make (as long as he's happy with the new API).
I'm not convinced by this. The names of the methods are literally the names of the TS compiler and they do what they say they do. For example your |
This PR add a new assertion API.
Planned features
(not.)identicalTo
(not.)assignableTo
(not.)subtypeOf
toThrowError
with code and/or message matching(not.)toBeDeprecated
(not.)toBeInternal
toHaveDocBlock
toHaveDocBlockTag
print
toBeNever
,toBeNull
, ...In addition to being more descriptive, decoupling the expected type from the type to be compared makes the bug #142 with generics disappear by design.