tsdjs/tsd

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

davidsu opened this issue · 3 comments

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.

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>

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.

See #196 for discussion on this.