refactor(compiler-cli): define type alias for the required delegation pattern (#39604)

The type alias allows for this pattern to be more easily used in other
areas of the compiler code. The current usages of this pattern have been
updated to use the type alias.

PR Close #39604
This commit is contained in:
JoostK 2020-11-08 16:13:42 +01:00 committed by atscott
parent 8e17dc0278
commit 7c161e1679
3 changed files with 13 additions and 22 deletions

View File

@ -15,7 +15,7 @@ import {FactoryGenerator, isShim, ShimAdapter, ShimReferenceTagger, SummaryGener
import {FactoryTracker, PerFileShimGenerator, TopLevelShimGenerator} from '../../shims/api';
import {TypeCheckShimGenerator} from '../../typecheck';
import {normalizeSeparators} from '../../util/src/path';
import {getRootDirs, isDtsPath, isNonDeclarationTsPath} from '../../util/src/typescript';
import {getRootDirs, isNonDeclarationTsPath, RequiredDelegations} from '../../util/src/typescript';
import {ExtendedTsCompilerHost, NgCompilerAdapter, NgCompilerOptions, UnifiedModulesHost} from '../api';
// A persistent source of bugs in CompilerHost delegation has been the addition by TS of new,
@ -23,15 +23,6 @@ import {ExtendedTsCompilerHost, NgCompilerAdapter, NgCompilerOptions, UnifiedMod
// the delegating host doesn't implement or delegate them. This causes subtle runtime failures. No
// more. This infrastructure ensures that failing to delegate a method is a compile-time error.
/**
* Represents the `ExtendedTsCompilerHost` interface, with a transformation applied that turns all
* methods (even optional ones) into required fields (which may be `undefined`, if the method was
* optional).
*/
export type RequiredCompilerHostDelegations = {
[M in keyof Required<ExtendedTsCompilerHost>]: ExtendedTsCompilerHost[M];
};
/**
* Delegates all methods of `ExtendedTsCompilerHost` to a delegate, with the exception of
* `getSourceFile` and `fileExists` which are implemented in `NgCompilerHost`.
@ -40,7 +31,7 @@ export type RequiredCompilerHostDelegations = {
* generated for this class.
*/
export class DelegatingCompilerHost implements
Omit<RequiredCompilerHostDelegations, 'getSourceFile'|'fileExists'> {
Omit<RequiredDelegations<ExtendedTsCompilerHost>, 'getSourceFile'|'fileExists'> {
constructor(protected delegate: ExtendedTsCompilerHost) {}
private delegateMethod<M extends keyof ExtendedTsCompilerHost>(name: M):
@ -89,7 +80,7 @@ export class DelegatingCompilerHost implements
* `ExtendedTsCompilerHost` methods whenever present.
*/
export class NgCompilerHost extends DelegatingCompilerHost implements
RequiredCompilerHostDelegations, ExtendedTsCompilerHost, NgCompilerAdapter {
RequiredDelegations<ExtendedTsCompilerHost>, ExtendedTsCompilerHost, NgCompilerAdapter {
readonly factoryTracker: FactoryTracker|null = null;
readonly entryPoint: AbsoluteFsPath|null = null;
readonly constructionDiagnostics: ts.Diagnostic[];

View File

@ -9,15 +9,7 @@
import * as ts from 'typescript';
import {copyFileShimData, ShimReferenceTagger} from '../../shims';
/**
* Represents the `ts.CompilerHost` interface, with a transformation applied that turns all
* methods (even optional ones) into required fields (which may be `undefined`, if the method was
* optional).
*/
export type RequiredCompilerHostDelegations = {
[M in keyof Required<ts.CompilerHost>]: ts.CompilerHost[M];
};
import {RequiredDelegations} from '../../util/src/typescript';
/**
* Delegates all methods of `ts.CompilerHost` to a delegate, with the exception of
@ -27,7 +19,7 @@ export type RequiredCompilerHostDelegations = {
* generated for this class.
*/
export class DelegatingCompilerHost implements
Omit<RequiredCompilerHostDelegations, 'getSourceFile'|'fileExists'|'writeFile'> {
Omit<RequiredDelegations<ts.CompilerHost>, 'getSourceFile'|'fileExists'|'writeFile'> {
constructor(protected delegate: ts.CompilerHost) {}
private delegateMethod<M extends keyof ts.CompilerHost>(name: M): ts.CompilerHost[M] {

View File

@ -149,3 +149,11 @@ export function isAssignment(node: ts.Node): node is ts.BinaryExpression {
* Asserts that the keys `K` form a subset of the keys of `T`.
*/
export type SubsetOfKeys<T, K extends keyof T> = K;
/**
* Represents the type `T`, with a transformation applied that turns all methods (even optional
* ones) into required fields (which may be `undefined`, if the method was optional).
*/
export type RequiredDelegations<T> = {
[M in keyof Required<T>]: T[M];
};