-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Force Override Declarations Types #36146
Comments
I guess this would work so long as there's only one file like this. I do have some apprehension since users might use this more often in place of actually fixing things on DefinitelyTyped. |
This could be used as a temporary measure because type definitions have to be reviewed before being updated on DefinitelyTyped. There also no need for one override file, since you can create a user based folder called override and place declaration files with the name of the module your trying to override. Because files can’t have the same name there will be no duplicates of modular overrides. |
I want this feature too. I use webpack in my project, it has declare the declare global {
interface __WebpackProcess {
env: any
}
declare var process: __WebpackProcess
} It declare |
This is like the dual of #31894. |
I have a need for this too. For example, I'd like to tighten up the type for QUnit's assert.ok to ok(state: boolean, message?: string): void; in a project (but don't think the DT types should be that strict). There's no good way to do this (at least that I'm aware of) short of redefining all of the QUnit types locally and not including |
I have a similar need, where I imported a library which is partly typed, and when I do declaration merging/module augmenting for that library, I'm being locked in "declarations must have the same type" issue for days. |
It would be useful also for "special cases" where typings are used to discourage use of API params which are actually valid. E.g. Stipe's create source API method: stripe/stripe-node#974 |
Plugins are a good example of a valid use case.
Currently the ugly hack is to automate the process of commenting existing declarations using patch-package (links to real life example of a plugin) |
I'm running into similar problems: I have a library that uses JSX but not React. Since React types are global, when both my library and React are installed, the types clash. I would love to be able to import my types just in the files that use my library without disturbing the typing in other files. |
+1! Just wanted to add another use case for this I've encountered: We use the TypeORM library in a large web application and a few of it's "findBy"-style methods are overly permissive. It's easy to pass arguments which actually have no effect on the generated SQL but seem like they would. We'd like to disallow certain usages as a team by narrowing the type declarations but the package provides it's own types so our only option is to fork it. We'd love to have an overrides file where we could forcibly declare a narrower input type for just a few methods and call it a day! |
@bengotow you could prevent that by writing a custom tslint rule |
How it's going |
Any progress? |
it would be great to have because with that we can fix cases like this emotion-js/emotion#1257 |
I love this idea. I really hope this gets added in next major update! |
My use case: adding project-specific documentation to the existing types for NextJS.
Tx 👍 There is some interesting discussion of further workarounds/hacks over at SO: How to overwrite incorrect TypeScript type definition installed via @types/package. |
Any update? |
1 similar comment
Any update? |
We had some casual conversations about this and are basically terrified of how it would work in practice as soon as more than one person starts using it. What happens when multiple files try to override? What happens when something on DefinitelyTyped claims to override something? What happens if two packages override a global in ways that they both depend on "sticking"? How does a user resolve conflicts? Can you override an entire namespace? We'll look at it again, though. |
Thanks! It might make sense to look at two solutions for similar problems in the ecosystem:
Based on the discussions in this thread, the first idea might work for TypeScript by having a setting in |
Yeah, I think a tsconfig-based mechanism is the thing that makes the most sense. The problem from there is figuring out the granularity. For "These defs are totally bad and I want to use my own", that's fine. But it'd be cumbersome to say "If you want to fix this one type in this file, you need to make an entire copy of it (and keep it in sync with everything else)". Then there's the separate question if this is an override of a module name or a file - both have use cases IMHO, since presumably at least some of the time you need to override a global definition. |
@antoniopresto - interesting solution - hadn't thought of this before! I get the error "Ambient modules cannot be nested in other modules or namespaces.ts(2435)" when I wrap my module in If I try to override the module just by declare module, I'm seeing this error in on the export line: "Exports and export assignments are not permitted in module augmentations.ts(2666)" I wonder if there's something setting your project that's letting you do this? Does I'm really hoping for something like an |
@dac09 @darch/schema is installed. {
"ts-node": {
"transpileOnly": true,
"compilerOptions": {
"module": "commonjs"
},
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
"baseUrl": "./src",
"paths": {
"@utils/*": ["utils/*"],
"@core/*": ["core/*"],
"@services/*": ["services/*"],
"@appTypes/*": ["types/*"],
"@entity/*": ["entity/*"]
},
"lib": ["es5", "es6", "es7", "esnext", "dom", "es2020"],
"declaration": true,
"target": "es5",
"module": "esnext",
"removeComments": false,
"esModuleInterop": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"strict": true,
"skipLibCheck": true,
"strictPropertyInitialization": false,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"downlevelIteration": true,
"noImplicitAny": false
},
"include": ["./src/**/*"]
}
|
@dac09 are you also using a |
Hi Antonio, yes I am. The file is an ambient declaration that currently “merges” the interfaces for “CurrentUser” (and works) - so don’t see any reason why it’s different. Anyone else have any thoughts what the difference might be? I have a feeling it’s the “skipLibCheck” flag being enabled in your project - the implications of which I’m unsure of. You can actually see this behaviour in any RedwoodJS project, where the ambient declarations sit in “.redwood/types”, after type generation. |
Any progress on this? Thanks! |
The solution from @antoniopresto works for me in TypeScript v4.9. |
Just a reminder, this not work for libraries, since we are using global declaration, which is ignored from bundled typings |
Can you help me understand what's wrong here? // "typescript": "^4.6.3"
// node-docker-api.d.ts
import { Container as OriginContainer } from 'node-docker-api/lib/container';
declare module 'node-docker-api/lib/container' {
type Container = Omit<OriginContainer, 'data'> & {
Warnings: string[];
data: {
Id: string;
Names: string[];
Image: string;
ImageID: string;
Command: string;
Created: number;
Ports: number[];
Labels: object;
State: 'exited' | 'running';
Status: string;
HostConfig: { NetworkMode: string };
NetworkSettings: any;
Mounts: any[];
};
id: string;
};
}
// another module
import { Container } from 'node-docker-api/lib/container';
// ...
const container: Container = containers.find(...)
if (container.data.State !== 'exited') {
await container.stop();
}
// tsconfig.json
{
....
"typeRoots": [
"node_modules/@types",
"./src/types"
],
"types": [
"jest"
],
} I see that this is has some impact but doesn't override existed interface I've been trying interface instead of type, rename module name, restart ts server and few another ways to initiate declare module and it doesn't seem to work |
declare module and it doesn't seem to work
declare global {
module '@darch/schema' {
export * from '@darch/schema'; // 👈🏼 export the same module @denbon05 you missed the re export line? |
@antoniopresto yes I tried this and still have an error :/ |
I managed to do the override like so: declare module '@darch/schema' {
function createTypeFn(def:{
union: [
'string',
'int',
'[float]',
],
}): "WHATEVER2";
export { createTypeFn as createType };
} |
Another similar issue - #25495 |
How do I override Components inside lib.dom, which is not a module to be import. |
Hello @antoniopresto, thanks for the info! Do you have any tips on how I can override a type so that the bundle can recognize it? I have a components package and I want to override a type (DefaultTheme) from a dependency called styled-components. This way, our developers won't have to manually override it in their apps. When I create a .d.ts file, it successfully overrides the type within the package. However, it is ignored when the package is bundled and used by another app. |
Any progress on this? Thanks! |
I have another instance of this where I'm using the styled-components guide for adding a global theme type per https://styled-components.com/docs/api#create-a-declarations-file, but their base type has an index ( This is what I've tried that doesn't seem to work:
It will allow me to access keys off of Any ideas on how to solve this? |
This works for me |
How do you override a single function in the package without having to redeclare everything in module you're overwriting/over-declaring? |
I've a similar use case which is much more functional: export class MyAPI {
...
search: SearchAPI<any> //some search api class among other built-in apis
...
} The result depends on the user account, so the generic sdk needs generic response. However, I also have a CLI that creates declare module "my-api-sdk" {
export interface MyAPI {
search: SearchAPI<TicketRecord | ConcertRecord | ArtistRecord>
}
} It would be awesome if my Is there any other way to do this currently? |
I saw this solution, but I also have similar issue as was mentioned above - I would have to redeclare the entire class to overwrite single property. To me, much cleaner solution would be explicit type override in declaration merging. |
Search Terms
declaration
module
merging
override
interface
Suggestion
Add a way to force override declarations for modules in the workspace. Typescript allows you to create a global.d.ts to add global declarations. How about an override.d.ts or an *.override.d.ts file to override existing modules declarations in the user workspace.
Use Cases
Lets say you install a node module package and type. You see that the type parameter isn't type safe so you use declaration merging to create a more type safe declaration. However, when you use the module type as a variables type or choose to extending it, it automatically uses the types folder declaration first since the type parameter used fits the node_modules declaration type parameter, however that type would not fit the type parameter the user created. This is because declaration merging selects the most appropriate types in order. If the type was to not match the first declaration type it would move on until reaching the appropriate type, which wouldn't work in this use case.
Examples
As you can see the type is accepted as the node modules declaration type instead of a user defined declaration type. There no other way of overriding it other than removing it manually from the the node_modules type file.
Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: