TypeScript中如何覆盖其他文件导入的函数?解决只读属性报错
The Problem
You've exported a function getPerson directly from msq.ts:
// msq.ts export function getPerson(): Promise<{ name: string, id: number }> { return new Promise((resolve, reject) => { setTimeout(() => { resolve({ name: "manas", id: 2 }); }, 5000); }) }
When you try to reassign this function in app.ts, TypeScript throws an error saying it's a read-only property:
// app.ts import * as msq from "../msq"; // ❌ Error: can't assign to getPerson because it is a read-only property msq.getPerson = function():Promise<{name:string,id:number}>{ return Promise.resolve({name:"manas",id:2}); }
Why This Happens
ES modules treat direct exports (like export function) as read-only bindings. This is part of the official module specification—top-level exports can't be reassigned after being imported.
Solutions
1. Wrap the Function in an Exported Object (Best for Non-Testing Scenarios)
The cleanest fix is to export your function as a property of an object instead of a top-level export. Object properties are mutable, so you can modify them freely:
Update msq.ts:
// msq.ts export const api = { getPerson(): Promise<{ name: string, id: number }> { return new Promise((resolve, reject) => { setTimeout(() => { resolve({ name: "manas", id: 2 }); }, 5000); }); } };
Then in app.ts:
// app.ts import { api } from "../msq"; // ✅ No error—we're modifying an object property api.getPerson = function(): Promise<{ name: string, id: number }> { return Promise.resolve({ name: "manas", id: 2 }); };
2. Use Type Assertion to Bypass Read-Only Check (Not Recommended)
If you can't modify msq.ts for some reason, you can use a type assertion to tell TypeScript to treat the export as writable. This skips type safety, so only use this for temporary debugging or edge cases:
// app.ts import * as msq from "../msq"; // Cast the module to a mutable type to bypass checks (msq as { getPerson: () => Promise<{ name: string, id: number }> }).getPerson = () => { return Promise.resolve({ name: "manas", id: 2 }); };
⚠️ Warning: This bypasses TypeScript's compile-time checks. If you mismatch the function signature, you'll get runtime errors instead of helpful warnings.
3. Mock the Function for Testing (If Using Jest/Vitest)
If you're trying to mock this function for tests, use your testing framework's built-in mocking tools instead of manual reassignment. For example, with Jest:
// app.test.ts import * as msq from "../msq"; // Mock the module while preserving other original exports jest.mock("../msq", () => ({ ...jest.requireActual("../msq"), getPerson: jest.fn(() => Promise.resolve({ name: "manas", id: 2 })) })); // Use the mocked function in tests test("uses mocked getPerson", async () => { const result = await msq.getPerson(); expect(result).toEqual({ name: "manas", id: 2 }); });
This is the standard approach for testing and doesn't require changing your original module structure.
内容的提问来源于stack exchange,提问作者manas

