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

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IDisposable } from 'vs/base/common/lifecycle';
import { IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation';
import { IConstructorSignature1, BrandedService } from 'vs/platform/instantiation/common/instantiation';
import { IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
import { ProxyIdentifier } from 'vs/workbench/services/extensions/common/proxyIdentifier';
@@ -13,12 +13,12 @@ export type IExtHostNamedCustomer<T extends IDisposable> = [ProxyIdentifier<T>,
export type IExtHostCustomerCtor<T extends IDisposable> = IConstructorSignature1<IExtHostContext, T>;
export function extHostNamedCustomer<T extends IDisposable>(id: ProxyIdentifier<T>) {
return function (ctor: IExtHostCustomerCtor<T>): void {
return function <Services extends BrandedService[]>(ctor: { new(context: IExtHostContext, ...services: Services): T }): void {
ExtHostCustomersRegistryImpl.INSTANCE.registerNamedCustomer(id, ctor);
};
}
export function extHostCustomer<T extends IDisposable>(ctor: IExtHostCustomerCtor<T>): void {
export function extHostCustomer<T extends IDisposable, Services extends BrandedService[]>(ctor: { new(context: IExtHostContext, ...services: Services): T }): void {
ExtHostCustomersRegistryImpl.INSTANCE.registerCustomer(ctor);
}