TypeScript
                                
                                 TypeScript copied to clipboard
                                
                                    TypeScript copied to clipboard
                            
                            
                            
                        TSC emits invalid .d.ts file with reserved keywords in identifier position
Bug Report
π Search Terms
delete reserved keyword .d.ts .d.ts reserved keyword 
π Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about invalid .d.ts types
β― Playground Link
Playground link with relevant code
π» Code
const obj1 = {
    delete: "foobar"
};
const obj2 = {
  x: obj1.delete
};
export default obj2;
π Actual behavior
The emitted .d.ts file contains delete in an identifier position. This in turns triggers an error when consumed: Identifier expected. 'delete' is a reserved word that cannot be used here.
Generated .d.ts:
export default obj2;
declare namespace obj2 {
    import x = obj1.delete;
    export { x };
}
declare namespace obj1 {
    const _delete: string;
    export { _delete as delete };
}
π Expected behavior
The generated .d.ts file should be valid.
Further notes
- Invalid .d.tsfiles are generated both if the input is a.jsor.tsfile
- I did not find any combination of flags/options/versions that would generate a valid .d.tsfile.
- I did find a workaround by altering the source file π
Workaround
This issue can currently be worked around by using ["delete"] instead of .delete. E.g. this:
const obj1 = {
    delete: "foobar"
};
const obj2 = {
  x: obj1["delete"]
};
export default obj2;
Generates the following valid .d.ts:
export default obj2;
declare namespace obj2 {
    const x: string;
}
I think instead of modifying the declaration emitter (since there's not really an otherwise-legal thing to emit here), we can change the parse rule on this line to allow reserved words, since we know we can emit obj1['delete'] even when this occurs in non-ambient contexts
import x = obj1.delete;
Wait why is { x: obj1.delete } allowed but import x = obj1.delete isnβt
In ES3, x.delete (or other reserved words) was illegal, so there's some logic around that which is incorrectly being applied here
Updating to TypeScript v5.4.2 has resulted in the error:
Identifier expected. 'delete' is a reserved word that cannot be used here. ts(1359)
In places like this in JSDoc where you link to a property called delete:
https://github.com/jaydenseric/graphql-react/blob/5525aca4e5ba5aad5115e56de92bf5ab4acbd2c9/cacheDelete.mjs#L11
E.g:
/** {@link Foo.delete `delete`} */
This (bug?) is a breaking change in a TypeScript semver minor release. It's not clear yet how to workaround the issue, without no longer linking these things.