Our code currently uses the `IConstructorSignature` types in a two main ways:

- As argument types in functions that take a service constructor.
- As return types or property types when we expose a service constructor in the API

This first usage is not valid with strict function types. The reason is that the `IConstructorSignature` types takes a rest array of `...services: BrandedService[]` , while the concrete constructors you pass in use actual services. With strict function types, you cannot convert the concrete constructor type to an `IConstructorSignature` because this would drop important type information that the implementation needs. As an example

```ts
class Foo {
    constructor(@ILogService service: ILogService) {}
}

registerFoo(Foo);

// The type of `ctor` inlines `IConstructorSignature0`
function registerFoo(ctor: { new(....serivces: BrandedService[]): Foo}) {
   // When registerFoo(Foo) is called, the implementation here would need to know that
   // ctor needs to be invoked with exactly one `ILogService`. However the type of `IConstructorSignature0`
   // does not express this. Strict function types therefore disallows this conversion
}
```

To fix this, I have converted a few places were we were taking `IConstructorSignature` arguments so that they preserve the full type of the constructor. This fixed over half of our 900 strict function type errors. Unfortunatly I can not figure out a more elegant way to express this besides inlining the types

However, even after this change, we still need to figure out how to deal with:

- Places in the code where `IConstructorSignature` is exposed as a return type or object property
- How to deal with all of our descriptor types (such as `SyncActionDescriptor`)
This commit is contained in:
Matt Bierner
2019-11-13 14:42:42 -08:00
committed by GitHub
parent 92caa97a1a
commit a77da1b1d8
6 changed files with 17 additions and 17 deletions

View File

@@ -16,7 +16,7 @@ import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
import { CommandsRegistry, ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IConstructorSignature1, ServicesAccessor as InstantiationServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IConstructorSignature1, ServicesAccessor as InstantiationServicesAccessor, BrandedService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindings, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -303,7 +303,7 @@ export function registerInstantiatedEditorAction(editorAction: EditorAction): vo
EditorContributionRegistry.INSTANCE.registerEditorAction(editorAction);
}
export function registerEditorContribution(id: string, ctor: IEditorContributionCtor): void {
export function registerEditorContribution<Services extends BrandedService[]>(id: string, ctor: { new(editor: ICodeEditor, ...services: Services): IEditorContribution }): void {
EditorContributionRegistry.INSTANCE.registerEditorContribution(id, ctor);
}
@@ -355,7 +355,7 @@ class EditorContributionRegistry {
this.editorCommands = Object.create(null);
}
public registerEditorContribution(id: string, ctor: IEditorContributionCtor): void {
public registerEditorContribution<Services extends BrandedService[]>(id: string, ctor: { new(editor: ICodeEditor, ...services: Services): IEditorContribution }): void {
this.editorContributions.push({ id, ctor });
}