diff --git a/type-definitions/immutable.d.ts b/type-definitions/immutable.d.ts index 0331a54bc..7bd59b2e2 100644 --- a/type-definitions/immutable.d.ts +++ b/type-definitions/immutable.d.ts @@ -91,6 +91,16 @@ */ declare namespace Immutable { + /** @ignore */ + type OnlyObject = Extract; + + /** @ignore */ + type ContainObject = OnlyObject extends object + ? OnlyObject extends never + ? false + : true + : false; + /** * @ignore * @@ -100,14 +110,14 @@ declare namespace Immutable { export type DeepCopy = T extends Record ? // convert Record to DeepCopy plain JS object { - [key in keyof R]: DeepCopy; + [key in keyof R]: ContainObject extends true ? unknown : R[key]; } : T extends Collection.Keyed ? // convert KeyedCollection to DeepCopy plain JS object { [key in KeyedKey extends string | number | symbol ? KeyedKey - : string]: DeepCopy; + : string]: V extends object ? unknown : V; } : // convert IndexedCollection or Immutable.Set to DeepCopy plain JS array T extends Collection @@ -118,7 +128,9 @@ declare namespace Immutable { ? Array> : T extends object // plain JS object are converted deeply ? { - [ObjectKey in keyof T]: DeepCopy; + [ObjectKey in keyof T]: ContainObject extends true + ? unknown + : T[ObjectKey]; } : // other case : should be kept as is T; diff --git a/type-definitions/ts-tests/deepCopy.ts b/type-definitions/ts-tests/deepCopy.ts index dc64f1533..a3240d3c1 100644 --- a/type-definitions/ts-tests/deepCopy.ts +++ b/type-definitions/ts-tests/deepCopy.ts @@ -23,10 +23,12 @@ import { List, Map, Record, Set, Seq, DeepCopy, Collection } from 'immutable'; // $ExpectType { [x: string]: string; } type StringKey = DeepCopy>; - // $ExpectType { [x: string]: object; } + // should be `{ [x: string]: object; }` but there is an issue with circular references + // $ExpectType { [x: string]: unknown; } type ObjectKey = DeepCopy>; - // $ExpectType { [x: string]: object; [x: number]: object; } + // should be `{ [x: string]: object; [x: number]: object; }` but there is an issue with circular references + // $ExpectType { [x: string]: unknown; [x: number]: unknown; } type MixedKey = DeepCopy>; // $ExpectType string[] @@ -55,10 +57,12 @@ import { List, Map, Record, Set, Seq, DeepCopy, Collection } from 'immutable'; { // Nested - // $ExpectType { map: { [x: string]: string; }; list: string[]; set: string[]; } + // should be `{ map: { [x: string]: string; }; list: string[]; set: string[]; }` but there is an issue with circular references + // $ExpectType { map: unknown; list: unknown; set: unknown; } type NestedObject = DeepCopy<{ map: Map; list: List; set: Set; }>; - // $ExpectType { map: { [x: string]: string; }; } + // should be `{ map: { [x: string]: string; }; }`, but there is an issue with circular references + // $ExpectType { map: unknown; } type NestedMap = DeepCopy>>; } @@ -68,6 +72,51 @@ import { List, Map, Record, Set, Seq, DeepCopy, Collection } from 'immutable'; type Article = Record<{ title: string; tag: Tag; }>; type Tag = Record<{ name: string; article: Article; }>; - // $ExpectType { title: string; tag: { name: string; article: any; }; } + // should handle circular references here somehow + // $ExpectType { title: string; tag: unknown; } type Circular = DeepCopy
; } + +{ + // Circular references #1957 + + class Foo1 extends Record<{ + foo: undefined | Foo1; + }>({ + foo: undefined + }) { + } + + class Foo2 extends Record<{ + foo?: Foo2; + }>({ + foo: undefined + }) { + } + + class Foo3 extends Record<{ + foo: null | Foo3; + }>({ + foo: null + }) { + } + + // $ExpectType { foo: unknown; } + type DeepFoo1 = DeepCopy; + + // $ExpectType { foo?: unknown; } + type DeepFoo2 = DeepCopy; + + // $ExpectType { foo: unknown; } + type DeepFoo3 = DeepCopy; + + class FooWithList extends Record<{ + foos: undefined | List; + }>({ + foos: undefined + }) { + } + + // $ExpectType { foos: unknown; } + type DeepFooList = DeepCopy; +} diff --git a/type-definitions/ts-tests/record.ts b/type-definitions/ts-tests/record.ts index c245cf310..559ad30f9 100644 --- a/type-definitions/ts-tests/record.ts +++ b/type-definitions/ts-tests/record.ts @@ -88,7 +88,8 @@ import { List, Map, Record, RecordOf, Set } from 'immutable'; // $ExpectType { map: Map; list: List; set: Set; } withMap.toJSON(); - // $ExpectType { map: { [x: string]: string; }; list: string[]; set: string[]; } + // should be `{ map: { [x: string]: string; }; list: string[]; set: string[]; }` but there is an issue with circular references + // $ExpectType { map: unknown; list: unknown; set: unknown; } withMap.toJS(); } @@ -101,7 +102,8 @@ import { List, Map, Record, RecordOf, Set } from 'immutable'; const line = Line({}); - // $ExpectType { size?: { distance: string; } | undefined; color?: string | undefined; } + // should be { size?: { distance: string; } | undefined; color?: string | undefined; } but there is an issue with circular references + // $ExpectType { size?: unknown; color?: string | undefined; } line.toJS(); }