diff --git a/types/seamless-immutable/index.d.ts b/types/seamless-immutable/index.d.ts index 046a60259a..a121e584f1 100644 --- a/types/seamless-immutable/index.d.ts +++ b/types/seamless-immutable/index.d.ts @@ -48,12 +48,19 @@ declare namespace SeamlessImmutable { merge(part: DeepPartial, config?: MergeConfig): T & ImmutableObject; - update(property: string, updaterFunction: (value: any, ...additionalParamters: any[]) => any, ...additionalArguments: any[]): ImmutableObject; - updateIn(propertyPath: Array, updaterFunction: (value: any, ...additionalParamters: any[]) => any, ...additionalArguments: any[]): ImmutableObject; + update(property: K, updaterFunction: (value: T[K], ...additionalParameters: any[]) => any, ...additionalArguments: any[]): T & ImmutableObject; + updateIn + (propertyPath: [ K ], updaterFunction: (value: T[K], ...additionalParameters: any[]) => any, ...additionalArguments: any[]): T & ImmutableObject; + updateIn + (propertyPath: [ K, L ], updaterFunction: (value: T[K][L], ...additionalParameters: any[]) => any, ...additionalArguments: any[]): T & ImmutableObject; + updateIn + (propertyPath: [ K, L, M ], updaterFunction: (value: T[K][L][M], ...additionalParameters: any[]) => any, ...additionalArguments: any[]): T & ImmutableObject; + updateIn + (propertyPath: [ K, L, M, N ], updaterFunction: (value: T[K][L][M][N], ...additionalParameters: any[]) => any, ...additionalArguments: any[]): T & ImmutableObject; - without(property: string): ImmutableObject; - without(...properties: string[]): ImmutableObject; - without(filter: (value: any, key: string) => boolean): ImmutableObject; + without(property: keyof T): TTarget & ImmutableObject; + without(...properties: Array): TTarget & ImmutableObject; + without(filter: (value: T[keyof T], key: keyof T) => boolean): TTarget & ImmutableObject; } export interface ImmutableArray { @@ -63,8 +70,7 @@ declare namespace SeamlessImmutable { flatMap(mapFunction: (item: T) => Array): TTarget[] & ImmutableArray; } - // an immutable object is both of Type T (i.e., looks like a normal T) and of type Immutable - export type Immutable = T & (ImmutableObject | ImmutableArray); + export type Immutable = ImmutableObject | ImmutableArray; export function from(obj: Array, options?: Options): Array & ImmutableArray; export function from(obj: T, options?: Options): T & ImmutableObject; diff --git a/types/seamless-immutable/seamless-immutable-tests.ts b/types/seamless-immutable/seamless-immutable-tests.ts index 6ab7fd25be..e5f7411d55 100644 --- a/types/seamless-immutable/seamless-immutable-tests.ts +++ b/types/seamless-immutable/seamless-immutable-tests.ts @@ -78,23 +78,26 @@ interface ExtendedUser extends User { }); // set: property name is strongly checked - const updatedUser: Immutable.ImmutableObject = immutableUser.set('firstName', 'Whirlwind'); + const updatedUser: User & Immutable.ImmutableObject = immutableUser.set('firstName', 'Whirlwind'); // setIn: property path is strongly checked for up to 4 arguments - const updatedUser2: Immutable.ImmutableObject = immutableUserEx.setIn(['address', 'line1'], 'Small house'); + const updatedUser2: ExtendedUser & Immutable.ImmutableObject = immutableUserEx.setIn(['address', 'line1'], 'Small house'); // asMutable const mutableUser1: User = immutableUser.asMutable(); const mutableUser2: User = immutableUser.asMutable({ deep: true }); // merge: merged part is strongly checked as a deeply partial object - const mergedUser: Immutable.ImmutableObject = immutableUserEx.merge({ address: { line1: 'Small house' }, firstName: 'Jack' }); -} + const mergedUser: User & Immutable.ImmutableObject = immutableUserEx.merge({ address: { line1: 'Small house' }, firstName: 'Jack' }); -const updatedUser: Immutable.ImmutableObject = extUser.update("firstName", (firstName): string => - firstName + "hehe" -); -const updatedInUser: Immutable.ImmutableObject = extUser.updateIn(["address", "line1"], (line): string => - line + "new address" -); -const userWithoutAddress: Immutable.ImmutableObject = extUser.without("address"); + // update: property name is strongly checked + const updatedUser3: User & Immutable.ImmutableObject = immutableUser.update('firstName', x => x.toLowerCase() + ' Whirlwind'); + + // updateIn: property path is strongly checked for up to 4 arguments + const updatedUser4: User & Immutable.ImmutableObject = immutableUserEx.updateIn([ 'address', 'line1' ], x => x.toLowerCase() + ' 43'); + + // without: the return type must be specified explicitly or it will be `any` + const simpleUser1: Immutable.ImmutableObject = immutableUserEx.without('address'); + const simpleUser2: User & Immutable.ImmutableObject = immutableUserEx.without('address'); + const simpleUser3: Immutable.ImmutableObject = immutableUserEx.without('firstName', 'lastName'); +}