Skip to content

Commit e310332

Browse files
authored
fix: preserve call signatures of target object in Object.assign (#76)
* fix: preserve call signatures of target object in Object.assign * ai: update CLAUDE.md
1 parent b899fca commit e310332

File tree

4 files changed

+29
-6
lines changed

4 files changed

+29
-6
lines changed

CLAUDE.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
77
This project generates alternative TypeScript standard library definitions with improved type safety. The architecture consists of:
88

99
- **`build/`** - TypeScript build system and generation logic
10+
1011
- `lib.ts` - Main script for generating improved lib definitions
1112
- `package.ts` - Script for building npm packages
1213
- `diff.ts` - Script for generating documentation diffs
@@ -25,6 +26,7 @@ This project generates alternative TypeScript standard library definitions with
2526
## Essential Commands
2627

2728
### Build Commands
29+
2830
```bash
2931
# Compile TypeScript build scripts
3032
npm run build:tsc
@@ -40,6 +42,9 @@ npm run build:diff
4042
```
4143

4244
### Testing
45+
46+
NOTE that you should run `npm run build:lib` and then `npm run build:package` before running tests to ensure the latest changes are reflected.
47+
4348
```bash
4449
# Run type-level tests in tests/ directory
4550
cd tests && npm test
@@ -49,10 +54,12 @@ cd tests && npx tsd
4954
```
5055

5156
### Development Workflow
57+
5258
1. Modify type definitions in `lib/` directory
53-
2. Run `npm run build:tsc && npm run build:lib` to regenerate
59+
2. Run `npm run build:lib && npm run build:generate` to regenerate the output
5460
3. Test changes with `cd tests && npm test`
55-
4. Generate packages with `npm run build:package` if needed
61+
62+
NOTE that the generated type definitions only take effect during the tests. When you want to debug the generated types, the only way is to write a test case in the `tests/` directory and run `npm test` to see how the types behave. Do not forget to run `npm run build:lib && npm run build:generate` after modifying the source definitions in `lib/`.
5663

5764
## Key Implementation Details
5865

@@ -63,7 +70,8 @@ cd tests && npx tsd
6370
- All changes prioritize type safety over convenience, potentially causing breaking changes in existing codebases
6471

6572
## Important Files
73+
6674
- `build/logic/generate.ts` - Core generation algorithm
67-
- `build/logic/ReplacementMap.ts` - Tracks lib modifications
75+
- `build/logic/ReplacementMap.ts` - Tracks lib modifications
6876
- `lib/es5.d.ts` - Main improvements to core JavaScript APIs
69-
- `tests/src/` - Type-level tests for verifications
77+
- `tests/src/` - Type-level tests for verifications

generated/lib.es2015.core.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ interface ObjectConstructor {
328328
assign<T extends {}, Ts extends readonly any[]>(
329329
target: T,
330330
...sources: Ts
331-
): Intersect<[T, ...Ts]>;
331+
): T & Intersect<Ts>;
332332

333333
/**
334334
* Returns an array of all symbol properties found directly on object o.

lib/lib.es2015.core.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ interface ObjectConstructor {
7272
assign<T extends {}, Ts extends readonly any[]>(
7373
target: T,
7474
...sources: Ts
75-
): Intersect<[T, ...Ts]>;
75+
): T & Intersect<Ts>;
7676

7777
/**
7878
* Returns an array of all symbol properties found directly on object o.

tests/src/es2015.core.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,19 @@ import { expectError, expectType } from "tsd";
3434
expectError(Object.getOwnPropertySymbols(null));
3535
const obj5 = Object.setPrototypeOf({ foo: 123 }, { bar: "wow" });
3636
expectType<{ foo: number } & { bar: string }>(obj5);
37+
38+
// https://github.com/uhyo/better-typescript-lib/issues/71
39+
// Object.assign should preserve function callability
40+
const func1 = () => 42;
41+
const funcWithProps = Object.assign(func1, { baz: "hello" });
42+
expectType<(() => number) & { baz: string }>(funcWithProps);
43+
expectType<number>(funcWithProps()); // Should be callable
44+
expectType<string>(funcWithProps.baz); // Should have the added property
45+
46+
const func2 = function(x: number): string { return x.toString(); };
47+
const funcWithProps2 = Object.assign(func2, { value: 123 }, { flag: true });
48+
expectType<((x: number) => string) & { value: number } & { flag: boolean }>(funcWithProps2);
49+
expectType<string>(funcWithProps2(42)); // Should be callable
50+
expectType<number>(funcWithProps2.value); // Should have added properties
51+
expectType<boolean>(funcWithProps2.flag);
3752
}

0 commit comments

Comments
 (0)