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

test pass with both expectType and expectNotType, pls help me understand #141

Open
davidsu opened this issue Jan 22, 2022 · 3 comments
Open

Comments

@davidsu
Copy link

davidsu commented Jan 22, 2022

This is an amazing library, thanks for it.
can you pls explain why this pass?

    type T2 = {a: {b: 1}}

    expectNotType<T2>({a:{b:1}})
    expectType<T2>({a:{b:1}})

    expectNotAssignable<T2>({a:{b:1}})
    expectAssignable<T2>({a:{b:1}})

I'd expect expectNotType<T2>({a:{b:1}}) and expectNotAssignable<T2>({a:{b:1}}) to fail.
thanks a lot.

@fictitious
Copy link

fictitious commented Nov 1, 2022

T2 is a type, and {a:{b:1}} argument is a value. In different contexts, TypeScript can infer different types for the same value.

expectType is declared as export const expectType = <T>(expression: T) => {} - its parameter type is explicitly declared to be the same as the generic type parameter, so {a: {b: 1}} literal argument has type T2 which is the same {a: {b: 1}}, and the types match.

expectNotType is declared as export const expectNotType = <T>(expression: any) => {}, its parameter type is any and literal argument type is widened to {a: {b: number}}, which is different from T2, and the types do not match.

From TypeScript point of view, everything works as expected.

Widening can be suppressed by using as const cast for the argument: expectNotType<T2>({a:{b:1}} as const) fails.

But from the user point of view, it's hard to justify why as const is needed to avoid situation when both seemingly opposite assertions are true.

I don't know if there's any other way to fix this besides choosing entirely different API for assertions. If the purpose is to test types, the assertions should use types, not values - one possible API could be

assertType<T2>().assignableTo<{a: {b: 1}}>();
assertType<T2>().notAssignableTo<{a: {b: 1}}>();

where functions do not take any arguments - for testing types of values, one will have to use .assignableTo<typeof someValue>

@tommy-mitchell
Copy link
Contributor

I'd think that const type parameters coming in TS 5.0 (microsoft/TypeScript#51865, TS 5.0 RC announcement) would help solve this issue.

Related discussion about API changes in #168.

@tommy-mitchell
Copy link
Contributor

See #196 for discussion on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants