diff --git a/common/changes/expect-type/fix-constructor-params_pr-245.json b/common/changes/expect-type/fix-constructor-params_pr-245.json new file mode 100644 index 00000000..3609a143 --- /dev/null +++ b/common/changes/expect-type/fix-constructor-params_pr-245.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "Fix constructor parameter comparison (#245)", + "type": "minor", + "packageName": "expect-type" + } + ], + "packageName": "expect-type", + "email": "mmkal@users.noreply.github.com" +} \ No newline at end of file diff --git a/packages/expect-type/readme.md b/packages/expect-type/readme.md index 42e52951..119e30e9 100644 --- a/packages/expect-type/readme.md +++ b/packages/expect-type/readme.md @@ -361,6 +361,34 @@ type E2 = {a: string; b: {c: string}} expectTypeOf().toMatchTypeOf() expectTypeOf().not.toEqualTypeOf() ``` + +Distinguish between classes with different constructors: + +```typescript +class A { + value: number + constructor(a: 1) { + this.value = a + } +} +class B { + value: number + constructor(b: 2) { + this.value = b + } +} + +expectTypeOf().not.toEqualTypeOf() + +class C { + value: number + constructor(c: 1) { + this.value = c + } +} + +expectTypeOf().toEqualTypeOf() +``` ### Within test frameworks diff --git a/packages/expect-type/src/__tests__/index.test.ts b/packages/expect-type/src/__tests__/index.test.ts index fda9eee5..199ac246 100644 --- a/packages/expect-type/src/__tests__/index.test.ts +++ b/packages/expect-type/src/__tests__/index.test.ts @@ -252,3 +252,29 @@ test('Detect the difference between regular and readonly properties', () => { expectTypeOf().toMatchTypeOf() expectTypeOf().not.toEqualTypeOf() }) + +test('Distinguish between classes with different constructors', () => { + class A { + value: number + constructor(a: 1) { + this.value = a + } + } + class B { + value: number + constructor(b: 2) { + this.value = b + } + } + + expectTypeOf().not.toEqualTypeOf() + + class C { + value: number + constructor(c: 1) { + this.value = c + } + } + + expectTypeOf().toEqualTypeOf() +}) diff --git a/packages/expect-type/src/index.ts b/packages/expect-type/src/index.ts index 5d5efb29..8faf81a3 100644 --- a/packages/expect-type/src/index.ts +++ b/packages/expect-type/src/index.ts @@ -20,15 +20,24 @@ export type IsNeverOrAny = Or<[IsNever, IsAny]> * - `{ readonly a: string }` vs `{ a: string }` * - `{ a?: string }` vs `{ a: string | undefined }` */ -type DeepBrand = IsAny extends true // avoid `any` matching `unknown` - ? Secret +export type DeepBrand = Or<[IsNever, IsAny, IsUnknown]> extends true // avoid `any`/`unknown`/`never` matching + ? { + type: 'special' + never: IsNever + any: IsAny + unknown: IsUnknown + } : T extends string | number | boolean | symbol | bigint | null | undefined - ? T + ? { + type: 'primitive' + value: T + } : T extends (...args: infer P) => infer R // avoid functions with different params/return values matching ? { type: 'function' params: DeepBrand

return: DeepBrand + constructorParams: DeepBrand> } : { type: 'object' @@ -36,6 +45,7 @@ type DeepBrand = IsAny extends true // avoid `any` matching `unknown` readonly: ReadonlyKeys required: RequiredKeys optional: OptionalKeys + constructorParams: DeepBrand> } export type RequiredKeys = Extract<