Skip to content

expectType "identical" description misleading for TS type usage, excess properties in arg not reported #229

@karlhorky

Description

@karlhorky

Hi, first of all, thanks for tsd, looks useful!

Looking at the Assertions -> expectType section in the readme, it appears that expectType<T>(expression: T) should assert that the types are identical:

expectType<T>(expression: T)

Asserts that the type of expression is identical to type T.

Scoping only to the context of the tsd TypeScript types (editor integration, tsc checks), "identical" is misleading: the type equality is only in a single direction, not bidirectional.

For example, the argument below with the excess property x is not reported as a TypeScript error (contrasted against expect-type, which correctly errors):

import { expectType } from "tsd";
import { expectTypeOf } from "expect-type";

type User = { id: number; name: string; email?: string; };
type UserExcess = { id: number; name: string; email?: string; y: string; };

type User2 = { id: number; name: string; email?: string; };
type UserExcess2 = { id: number; name: string; email?: string; x: string; };

expectType<User>({} as unknown as User2); // Correct: No error reported
expectType<UserExcess>({} as unknown as User2); // Correct: Error reported
expectType<User>({} as unknown as UserExcess2); // 💥 Incorrect: No error reported (false negative)

// expect-type `expectTypeOf().toEqualTypeOf()` gets this right
expectTypeOf<User2>().toEqualTypeOf<User>(); // Correct: No error reported
expectTypeOf<User2>().toEqualTypeOf<UserExcess>(); // Correct: Error reported
expectTypeOf<UserExcess2>().toEqualTypeOf<User>(); // Correct: Error reported
Image

TypeScript Playground

Suggested Solution

  1. Change the "identical" in the documentation to "assignable" or "compatible" or similar to avoid the word "identical" (or describe that it's only single-direction with other words)
  2. Possibly also: I saw that the implementation of expectType is the same as the implementation of expectAssignable - should one of those two be dropped?
  3. Possibly also: Offer a true "identical" utility (maybe named expectTypeStrict?) which will check in both directions, like expectTypeOf<>().toEqualTypeOf<>() from expect-type

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions