feat(core): support TypeScript 4.7 (#45749)

Adds support for TypeScript 4.7. Changes include:
* Bumping the TS version as well as some Bazel dependencies to include https://github.com/bazelbuild/rules_nodejs/pull/3420.
* Adding a backwards-compatibility layer for calls to `updateTypeParameterDeclaration`.
* Making `LView` generic in order to make it easier to type the context based on the usage. Currently the context can be 4 different types which coupled with stricter type checking would required a lot of extra casting all over `core`.
* Fixing a bunch of miscellaneous type errors.
* Removing assertions of `ReferenceEntry.isDefinition` in a few of the language service tests. The field isn't returned by TS anymore and we weren't using it for anything.
* Resolving in error in the language service that was caused by TS attempting to parse HTML files when we try to open them. Previous TS was silently setting them as `ScriptKind.Unknown` and ignoring the errors, but now it throws. I've worked around it by setting them as `ScriptKind.JSX`.

PR Close #45749
This commit is contained in:
Kristiyan Kostadinov
2022-04-29 14:38:15 +02:00
committed by Dylan Hunn
parent fcc548a95f
commit 29039fcdbc
48 changed files with 419 additions and 176 deletions
+1 -1
View File
@@ -35,7 +35,7 @@
"rollup": "^2.56.3",
"rollup-plugin-sourcemaps": "^0.6.3",
"terser": "^5.9.0",
"typescript": ">=4.6.2 <4.7"
"typescript": ">=4.6.2 <4.8"
},
"peerDependenciesMeta": {
"terser": {
@@ -93,8 +93,8 @@ export const spyProperty = <T, P extends keyof T>(ctx: T, prop: P): IPropertySpy
let value = ctx[prop];
const setMockValue = (mockValue: typeof value) => value = mockValue;
const setSpy = jasmine.createSpy(`set ${prop}`).and.callFake(setMockValue);
const getSpy = jasmine.createSpy(`get ${prop}`).and.callFake(() => value);
const setSpy = jasmine.createSpy(`set ${String(prop)}`).and.callFake(setMockValue);
const getSpy = jasmine.createSpy(`get ${String(prop)}`).and.callFake(() => value);
const installSpies = () => {
value = ctx[prop];
@@ -697,7 +697,7 @@ runInEachFileSystem(() => {
});
it('should correctly handle pre-release versions and version ranges', () => {
Object.assign(DEFAULT_NGCC_CONFIG.packages, {
Object.assign(DEFAULT_NGCC_CONFIG.packages!, {
'package-1': {
entryPoints: {
'./entry-point-1': {},
+1 -1
View File
@@ -66,7 +66,7 @@
},
"peerDependencies": {
"@angular/compiler": "0.0.0-PLACEHOLDER",
"typescript": ">=4.6.2 <4.7"
"typescript": ">=4.6.2 <4.8"
},
"repository": {
"type": "git",
@@ -10,6 +10,8 @@ import ts from 'typescript';
import {ClassDeclaration} from '../../reflection';
const PARSED_TS_VERSION = parseFloat(ts.versionMajorMinor);
/**
* A `Set` of `ts.SyntaxKind`s of `ts.Expression` which are safe to wrap in a `ts.AsExpression`
@@ -134,6 +136,21 @@ export function tsCallMethod(
/* argumentsArray */ args);
}
/**
* Updates a `ts.TypeParameter` declaration.
*
* TODO(crisbeto): this is a backwards-compatibility layer for versions of TypeScript less than 4.7.
* We should remove it once we have dropped support for the older versions.
*/
export function tsUpdateTypeParameterDeclaration(
node: ts.TypeParameterDeclaration, name: ts.Identifier, constraint: ts.TypeNode|undefined,
defaultType: ts.TypeNode|undefined): ts.TypeParameterDeclaration {
return PARSED_TS_VERSION < 4.7 ?
ts.factory.updateTypeParameterDeclaration(node, name, constraint, defaultType) :
(ts.factory.updateTypeParameterDeclaration as any)(
node, /* modifiers */[], name, constraint, defaultType);
}
export function checkIfClassIsExported(node: ClassDeclaration): boolean {
// A class is exported if one of two conditions is met:
// 1) it has the 'export' modifier.
@@ -12,7 +12,7 @@ import {ClassDeclaration, ReflectionHost} from '../../reflection';
import {TypeCtorMetadata} from '../api';
import {checkIfGenericTypeBoundsCanBeEmitted, ReferenceEmitEnvironment} from './tcb_util';
import {tsCreateTypeQueryForCoercedInput} from './ts_util';
import {tsCreateTypeQueryForCoercedInput, tsUpdateTypeParameterDeclaration} from './ts_util';
export function generateTypeCtorDeclarationFn(
node: ClassDeclaration<ts.ClassDeclaration>, meta: TypeCtorMetadata, nodeTypeRef: ts.EntityName,
@@ -244,11 +244,9 @@ function typeParametersWithDefaultTypes(params: ReadonlyArray<ts.TypeParameterDe
return params.map(param => {
if (param.default === undefined) {
return ts.factory.updateTypeParameterDeclaration(
/* node */ param,
/* name */ param.name,
/* constraint */ param.constraint,
/* defaultType */ ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword));
return tsUpdateTypeParameterDeclaration(
param, param.name, param.constraint,
ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword));
} else {
return param;
}
@@ -10,6 +10,7 @@ import ts from 'typescript';
import {OwningModule, Reference} from '../../imports';
import {DeclarationNode, ReflectionHost} from '../../reflection';
import {tsUpdateTypeParameterDeclaration} from './ts_util';
import {canEmitType, TypeEmitter} from './type_emitter';
@@ -73,11 +74,7 @@ export class TypeParameterEmitter {
const defaultType =
typeParam.default !== undefined ? emitter.emitType(typeParam.default) : undefined;
return ts.factory.updateTypeParameterDeclaration(
/* node */ typeParam,
/* name */ typeParam.name,
/* constraint */ constraint,
/* defaultType */ defaultType);
return tsUpdateTypeParameterDeclaration(typeParam, typeParam.name, constraint, defaultType);
});
}
@@ -480,7 +480,7 @@ describe('type check blocks', () => {
expect(tcb(TEMPLATE, DIRECTIVES))
.toContain(
'var _t1: i0.Dir = null!; ' +
'var _t2: typeof _t1["fieldA"] = null!; ' +
'var _t2: (typeof _t1)["fieldA"] = null!; ' +
'_t2 = (((ctx).foo)); ');
});
@@ -26,7 +26,7 @@ const MIN_TS_VERSION = '4.6.2';
* Note: this check is disabled in g3, search for
* `angularCompilerOptions.disableTypeScriptVersionCheck` config param value in g3.
*/
const MAX_TS_VERSION = '4.7.0';
const MAX_TS_VERSION = '4.8.0';
/**
* The currently used version of TypeScript, which can be adjusted for testing purposes using
@@ -105,8 +105,12 @@ describe('perform watch', () => {
expect(fs.existsSync(genPath)).toBe(true);
expect(fileExistsSpy!).toHaveBeenCalledWith(mainTsPath);
expect(fileExistsSpy!).toHaveBeenCalledWith(utilTsPath);
expect(getSourceFileSpy!).toHaveBeenCalledWith(mainTsPath, ts.ScriptTarget.ES5);
expect(getSourceFileSpy!).toHaveBeenCalledWith(utilTsPath, ts.ScriptTarget.ES5);
expect(getSourceFileSpy!).toHaveBeenCalledWith(mainTsPath, jasmine.objectContaining({
languageVersion: ts.ScriptTarget.ES5
}));
expect(getSourceFileSpy!).toHaveBeenCalledWith(utilTsPath, jasmine.objectContaining({
languageVersion: ts.ScriptTarget.ES5
}));
fileExistsSpy!.calls.reset();
getSourceFileSpy!.calls.reset();
+4 -3
View File
@@ -78,16 +78,17 @@ class ChainedInjector implements Injector {
constructor(private injector: Injector, private parentInjector: Injector) {}
get<T>(token: ProviderToken<T>, notFoundValue?: T, flags?: InjectFlags): T {
const value = this.injector.get(token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as T, flags);
const value = this.injector.get<T|typeof NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR>(
token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, flags);
if (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR ||
notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) {
notFoundValue === (NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as unknown as T)) {
// Return the value from the root element injector when
// - it provides it
// (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR)
// - the module injector should not be checked
// (notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR)
return value;
return value as T;
}
return this.parentInjector.get(token, notFoundValue, flags);
@@ -196,10 +196,10 @@ export function readPatchedData(target: any): LView|LContext|null {
return (typeof data === 'number') ? getLViewById(data) : data || null;
}
export function readPatchedLView(target: any): LView|null {
export function readPatchedLView<T>(target: any): LView<T>|null {
const value = readPatchedData(target);
if (value) {
return isLView(value) ? value : value.lView;
return (isLView(value) ? value : value.lView) as LView<T>;
}
return null;
}
+3 -2
View File
@@ -489,7 +489,7 @@ function lookupTokenUsingNodeInjector<T>(
// At this point, we have an injector which *may* contain the token, so we step through
// the providers and directives associated with the injector's corresponding node to get
// the instance.
const instance: T|null = searchTokensOnInjector<T>(
const instance: T|{}|null = searchTokensOnInjector<T>(
injectorIndex, lView, token, previousTView, flags, hostTElementNode);
if (instance !== NOT_FOUND) {
return instance;
@@ -803,7 +803,8 @@ function lookupTokenUsingEmbeddedInjector<T>(
// Before we go to the next LView, check if the token exists on the current embedded injector.
const embeddedViewInjector = currentLView[EMBEDDED_VIEW_INJECTOR];
if (embeddedViewInjector) {
const embeddedViewInjectorValue = embeddedViewInjector.get(token, NOT_FOUND as T, flags);
const embeddedViewInjectorValue =
embeddedViewInjector.get(token, NOT_FOUND as T | {}, flags);
if (embeddedViewInjectorValue !== NOT_FOUND) {
return embeddedViewInjectorValue;
}
@@ -10,6 +10,7 @@ import {assertDefined} from '../../util/assert';
import {getComponentViewByInstance} from '../context_discovery';
import {CONTEXT, RootContext, RootContextFlags, TVIEW} from '../interfaces/view';
import {getRootView} from '../util/view_traversal_utils';
import {detectChangesInternal, markViewDirty, scheduleTick, tickRootContext} from './shared';
/**
@@ -53,7 +54,7 @@ export function markDirty(component: {}): void {
* single change detection run. By default, the scheduler is `requestAnimationFrame`, but can
* be changed when calling `renderComponent` and providing the `scheduler` option.
*/
export function tick<T>(component: T): void {
export function tick(component: {}): void {
const rootView = getRootView(component);
const rootContext = rootView[CONTEXT] as RootContext;
tickRootContext(rootContext);
@@ -40,7 +40,7 @@ import {getOrCreateLViewCleanup, getOrCreateTViewCleanup, handleError, loadCompo
export function ɵɵlistener(
eventName: string, listenerFn: (e?: any) => any, useCapture?: boolean,
eventTargetResolver?: GlobalTargetResolver): typeof ɵɵlistener {
const lView = getLView();
const lView = getLView<{}|null>();
const tView = getTView();
const tNode = getCurrentTNode()!;
listenerInternal(
@@ -73,7 +73,7 @@ export function ɵɵlistener(
export function ɵɵsyntheticHostListener(
eventName: string, listenerFn: (e?: any) => any): typeof ɵɵsyntheticHostListener {
const tNode = getCurrentTNode()!;
const lView = getLView();
const lView = getLView<{}|null>();
const tView = getTView();
const currentDef = getCurrentDirectiveDef(tView.data);
const renderer = loadComponentRenderer(currentDef, tNode, lView);
@@ -114,7 +114,7 @@ function findExistingListener(
}
function listenerInternal(
tView: TView, lView: LView, renderer: Renderer3, tNode: TNode, eventName: string,
tView: TView, lView: LView<{}|null>, renderer: Renderer3, tNode: TNode, eventName: string,
listenerFn: (e?: any) => any, useCapture: boolean,
eventTargetResolver?: GlobalTargetResolver): void {
const isTNodeDirectiveHost = isDirectiveHost(tNode);
@@ -250,7 +250,7 @@ function executeListenerWithErrorHandling(
* (the procedural renderer does this already, so in those cases, we should skip)
*/
function wrapListener(
tNode: TNode, lView: LView, context: {}|null, listenerFn: (e?: any) => any,
tNode: TNode, lView: LView<{}|null>, context: {}|null, listenerFn: (e?: any) => any,
wrapWithPreventDefault: boolean): EventListener {
// Note: we are performing most of the work in the listener function itself
// to optimize listener registration.
@@ -73,7 +73,7 @@ interface TViewDebug extends ITView {
*
* Simple slice will keep the same type, and we need it to be LView
*/
export function cloneToLViewFromTViewBlueprint(tView: TView): LView {
export function cloneToLViewFromTViewBlueprint<T>(tView: TView): LView<T> {
const debugTView = tView as TViewDebug;
const lView = getLViewToClone(debugTView.type, tView.template && tView.template.name);
return lView.concat(tView.blueprint) as any;
@@ -387,9 +387,9 @@ export function attachLContainerDebug(lContainer: LContainer) {
attachDebugObject(lContainer, new LContainerDebug(lContainer));
}
export function toDebug(obj: LView): ILViewDebug;
export function toDebug(obj: LView|null): ILViewDebug|null;
export function toDebug(obj: LView|LContainer|null): ILViewDebug|ILContainerDebug|null;
export function toDebug<T>(obj: LView<T>): ILViewDebug<T>;
export function toDebug<T>(obj: LView<T>|null): ILViewDebug<T>|null;
export function toDebug<T>(obj: LView<T>|LContainer|null): ILViewDebug<T>|ILContainerDebug|null;
export function toDebug(obj: any): any {
if (obj) {
const debug = (obj as any).debug;
@@ -432,8 +432,8 @@ function toHtml(value: any, includeChildren: boolean = false): string|null {
return null;
}
export class LViewDebug implements ILViewDebug {
constructor(private readonly _raw_lView: LView) {}
export class LViewDebug<T = unknown> implements ILViewDebug<T> {
constructor(private readonly _raw_lView: LView<T>) {}
/**
* Flags associated with the `LView` unpacked into a more readable state.
@@ -453,8 +453,8 @@ export class LViewDebug implements ILViewDebug {
indexWithinInitPhase: flags >> LViewFlags.IndexWithinInitPhaseShift,
};
}
get parent(): ILViewDebug|ILContainerDebug|null {
return toDebug(this._raw_lView[PARENT]);
get parent(): ILViewDebug<T>|ILContainerDebug|null {
return toDebug<T>(this._raw_lView[PARENT] as LView<T>| LContainer | null);
}
get hostHTML(): string|null {
return toHtml(this._raw_lView[HOST], true);
@@ -462,7 +462,7 @@ export class LViewDebug implements ILViewDebug {
get html(): string {
return (this.nodes || []).map(mapToHTML).join('');
}
get context(): {}|null {
get context(): T {
return this._raw_lView[CONTEXT];
}
/**
@@ -498,8 +498,8 @@ export class LViewDebug implements ILViewDebug {
get childHead(): ILViewDebug|ILContainerDebug|null {
return toDebug(this._raw_lView[CHILD_HEAD]);
}
get next(): ILViewDebug|ILContainerDebug|null {
return toDebug(this._raw_lView[NEXT]);
get next(): ILViewDebug<T>|ILContainerDebug|null {
return toDebug<T>(this._raw_lView[NEXT] as LView<T>| LContainer | null);
}
get childTail(): ILViewDebug|ILContainerDebug|null {
return toDebug(this._raw_lView[CHILD_TAIL]);
@@ -534,11 +534,11 @@ export class LViewDebug implements ILViewDebug {
/**
* Normalized view of child views (and containers) attached at this location.
*/
get childViews(): Array<ILViewDebug|ILContainerDebug> {
const childViews: Array<ILViewDebug|ILContainerDebug> = [];
get childViews(): Array<ILViewDebug<T>|ILContainerDebug> {
const childViews: Array<ILViewDebug<T>|ILContainerDebug> = [];
let child = this.childHead;
while (child) {
childViews.push(child);
childViews.push(child as ILViewDebug<T>| ILContainerDebug);
child = child.next;
}
return childViews;
@@ -292,20 +292,20 @@ export function allocExpando(
* - updating static queries (if any);
* - creating child components defined in a given view.
*/
export function renderView<T>(tView: TView, lView: LView, context: T): void {
export function renderView<T>(tView: TView, lView: LView<T>, context: T): void {
ngDevMode && assertEqual(isCreationMode(lView), true, 'Should be run in creation mode');
enterView(lView);
try {
const viewQuery = tView.viewQuery;
if (viewQuery !== null) {
executeViewQueryFn(RenderFlags.Create, viewQuery, context);
executeViewQueryFn<T>(RenderFlags.Create, viewQuery, context);
}
// Execute a template associated with this view, if it exists. A template function might not be
// defined for the root component views.
const templateFn = tView.template;
if (templateFn !== null) {
executeTemplate(tView, lView, templateFn, RenderFlags.Create, context);
executeTemplate<T>(tView, lView, templateFn, RenderFlags.Create, context);
}
// This needs to be set before children are processed to support recursive components.
@@ -328,7 +328,7 @@ export function renderView<T>(tView: TView, lView: LView, context: T): void {
// in case a child component has projected a container. The LContainer needs
// to exist so the embedded views are properly attached by the container.
if (tView.staticViewQueries) {
executeViewQueryFn(RenderFlags.Update, tView.viewQuery!, context);
executeViewQueryFn<T>(RenderFlags.Update, tView.viewQuery!, context);
}
// Render child component views.
@@ -439,7 +439,7 @@ export function refreshView<T>(
// refresh, the template might not yet be inserted.
const viewQuery = tView.viewQuery;
if (viewQuery !== null) {
executeViewQueryFn(RenderFlags.Update, viewQuery, context);
executeViewQueryFn<T>(RenderFlags.Update, viewQuery, context);
}
// execute view hooks (AfterViewInit, AfterViewChecked)
@@ -507,7 +507,7 @@ export function renderComponentOrTemplate<T>(
}
function executeTemplate<T>(
tView: TView, lView: LView, templateFn: ComponentTemplate<T>, rf: RenderFlags, context: T) {
tView: TView, lView: LView<T>, templateFn: ComponentTemplate<T>, rf: RenderFlags, context: T) {
const prevSelectedIndex = getSelectedIndex();
const isUpdatePhase = rf & RenderFlags.Update;
try {
@@ -520,14 +520,14 @@ function executeTemplate<T>(
const preHookType =
isUpdatePhase ? ProfilerEvent.TemplateUpdateStart : ProfilerEvent.TemplateCreateStart;
profiler(preHookType, context);
profiler(preHookType, context as unknown as {});
templateFn(rf, context);
} finally {
setSelectedIndex(prevSelectedIndex);
const postHookType =
isUpdatePhase ? ProfilerEvent.TemplateUpdateEnd : ProfilerEvent.TemplateCreateEnd;
profiler(postHookType, context);
profiler(postHookType, context as unknown as {});
}
}
@@ -1995,7 +1995,7 @@ export function checkNoChangesInRootView(lView: LView): void {
}
function executeViewQueryFn<T>(
flags: RenderFlags, viewQueryFn: ViewQueriesFunction<{}>, component: T): void {
flags: RenderFlags, viewQueryFn: ViewQueriesFunction<T>, component: T): void {
ngDevMode && assertDefined(viewQueryFn, 'View queries function to execute must be defined.');
setCurrentQueryIndex(0);
viewQueryFn(flags, component);
+6 -6
View File
@@ -78,7 +78,7 @@ export interface OpaqueViewState {
* Keeping separate state for each view facilities view insertion / deletion, so we
* don't have to edit the data array based on which views are present.
*/
export interface LView extends Array<any> {
export interface LView<T = unknown> extends Array<any> {
/**
* Human readable representation of the `LView`.
*
@@ -180,7 +180,7 @@ export interface LView extends Array<any> {
* - For non-root components, the context is the component instance,
* - For inline views, the context is null.
*/
[CONTEXT]: {}|RootContext|null;
[CONTEXT]: T;
/** An optional Module Injector to be used as fall back after Element Injectors are consulted. */
readonly[INJECTOR]: Injector|null;
@@ -818,7 +818,7 @@ export const enum RootContextFlags {
* RootContext contains information which is shared for all components which
* were bootstrapped with {@link renderComponent}.
*/
export interface RootContext {
export interface RootContext<T = unknown> {
/**
* A function used for scheduling change detection in the future. Usually
* this is `requestAnimationFrame`.
@@ -836,7 +836,7 @@ export interface RootContext {
* RootComponents - The components that were instantiated by the call to
* {@link renderComponent}.
*/
components: {}[];
components: T[];
/**
* The player flushing handler to kick off all animations
@@ -935,7 +935,7 @@ export const unusedValueExportToPlacateAjd = 1;
* `LViewDebug` for easier debugging and test writing. It is the intent of `LViewDebug` to be used
* in tests.
*/
export interface LViewDebug {
export interface LViewDebug<T = unknown> {
/**
* Flags associated with the `LView` unpacked into a more readable state.
*
@@ -973,7 +973,7 @@ export interface LViewDebug {
*
* (Usually the component)
*/
readonly context: {}|null;
readonly context: T;
/**
* Hierarchical tree of nodes.
+2 -1
View File
@@ -9,6 +9,7 @@
import {PipeTransform} from '../change_detection/pipe_transform';
import {setInjectImplementation} from '../di/inject_switch';
import {RuntimeError, RuntimeErrorCode} from '../errors';
import {Type} from '../interface/type';
import {getFactoryDef} from './definition_factory';
import {setIncludeViewProviders} from './di';
@@ -83,7 +84,7 @@ function getPipeDef(name: string, registry: PipeDefList|null): PipeDef<any>|unde
}
if (ngDevMode) {
const lView = getLView();
const declarationLView = lView[DECLARATION_COMPONENT_VIEW];
const declarationLView = lView[DECLARATION_COMPONENT_VIEW] as LView<Type<unknown>>;
const context = declarationLView[CONTEXT];
const component = context ? ` in the '${context.constructor.name}' component` : '';
throw new RuntimeError(
+4 -4
View File
@@ -266,8 +266,8 @@ export function ɵɵdisableBindings(): void {
/**
* Return the current `LView`.
*/
export function getLView(): LView {
return instructionState.lFrame.lView;
export function getLView<T>(): LView<T> {
return instructionState.lFrame.lView as LView<T>;
}
/**
@@ -294,7 +294,7 @@ export function getTView(): TView {
*/
export function ɵɵrestoreView<T = any>(viewToRestore: OpaqueViewState): T {
instructionState.lFrame.contextLView = viewToRestore as any as LView;
return (viewToRestore as any as LView)[CONTEXT] as T;
return (viewToRestore as any as LView)[CONTEXT] as unknown as T;
}
@@ -658,7 +658,7 @@ export function leaveView() {
export function nextContextImpl<T = any>(level: number): T {
const contextLView = instructionState.lFrame.contextLView =
walkUpViews(level, instructionState.lFrame.contextLView!);
return contextLView[CONTEXT] as T;
return contextLView[CONTEXT] as unknown as T;
}
function walkUpViews(nestingLevel: number, currentView: LView): LView {
@@ -19,7 +19,7 @@ import {LContext} from '../interfaces/context';
import {DirectiveDef} from '../interfaces/definition';
import {TElementNode, TNode, TNodeProviderIndexes} from '../interfaces/node';
import {isLView} from '../interfaces/type_checks';
import {CLEANUP, CONTEXT, DebugNode, FLAGS, LView, LViewFlags, T_HOST, TVIEW, TViewType} from '../interfaces/view';
import {CLEANUP, CONTEXT, DebugNode, FLAGS, LView, LViewFlags, RootContext, T_HOST, TVIEW, TViewType} from '../interfaces/view';
import {stringifyForError} from './stringify_utils';
import {getLViewParent, getRootContext} from './view_traversal_utils';
@@ -67,7 +67,7 @@ export function getComponent<T>(element: Element): T|null {
context.component = getComponentAtNodeIndex(context.nodeIndex, lView);
}
return context.component as T;
return context.component as unknown as T;
}
@@ -83,7 +83,7 @@ export function getComponent<T>(element: Element): T|null {
* @publicApi
* @globalApi ng
*/
export function getContext<T>(element: Element): T|null {
export function getContext<T extends({} | RootContext)>(element: Element): T|null {
assertDomElement(element);
const context = getLContext(element)!;
const lView = context ? context.lView : null;
@@ -114,7 +114,7 @@ export function getOwningComponent<T>(elementOrDir: Element|{}): T|null {
while (lView[TVIEW].type === TViewType.Embedded && (parent = getLViewParent(lView)!)) {
lView = parent;
}
return lView[FLAGS] & LViewFlags.IsRoot ? null : lView[CONTEXT] as T;
return lView[FLAGS] & LViewFlags.IsRoot ? null : lView[CONTEXT] as unknown as T;
}
/**
@@ -129,8 +129,8 @@ export function getOwningComponent<T>(elementOrDir: Element|{}): T|null {
* @globalApi ng
*/
export function getRootComponents(elementOrDir: Element|{}): {}[] {
const lView = readPatchedLView(elementOrDir);
return lView !== null ? [...getRootContext(lView).components] : [];
const lView = readPatchedLView<{}>(elementOrDir);
return lView !== null ? [...getRootContext(lView).components as unknown as {}[]] : [];
}
/**
@@ -31,14 +31,14 @@ export function getLViewParent(lView: LView): LView|null {
*
* @param componentOrLView any component or `LView`
*/
export function getRootView(componentOrLView: LView|{}): LView {
export function getRootView<T>(componentOrLView: LView|{}): LView<T> {
ngDevMode && assertDefined(componentOrLView, 'component');
let lView = isLView(componentOrLView) ? componentOrLView : readPatchedLView(componentOrLView)!;
while (lView && !(lView[FLAGS] & LViewFlags.IsRoot)) {
lView = getLViewParent(lView)!;
}
ngDevMode && assertLView(lView);
return lView;
return lView as LView<T>;
}
/**
@@ -48,7 +48,7 @@ export function getRootView(componentOrLView: LView|{}): LView {
*
* @param viewOrComponent the `LView` or component to get the root context for.
*/
export function getRootContext(viewOrComponent: LView|{}): RootContext {
export function getRootContext<T>(viewOrComponent: LView<T>|{}): RootContext {
const rootView = getRootView(viewOrComponent);
ngDevMode &&
assertDefined(rootView[CONTEXT], 'RootView has no context. Perhaps it is disconnected?');
+4 -4
View File
@@ -60,11 +60,11 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T>, viewEngine_Int
private _cdRefInjectingView?: LView) {}
get context(): T {
return this._lView[CONTEXT] as T;
return this._lView[CONTEXT] as unknown as T;
}
set context(value: T) {
this._lView[CONTEXT] = value;
this._lView[CONTEXT] = value as unknown as {};
}
get destroyed(): boolean {
@@ -271,7 +271,7 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T>, viewEngine_Int
* See {@link ChangeDetectorRef#detach detach} for more information.
*/
detectChanges(): void {
detectChangesInternal(this._lView[TVIEW], this._lView, this.context);
detectChangesInternal(this._lView[TVIEW], this._lView, this.context as unknown as {});
}
/**
@@ -281,7 +281,7 @@ export class ViewRef<T> implements viewEngine_EmbeddedViewRef<T>, viewEngine_Int
* introduce other changes.
*/
checkNoChanges(): void {
checkNoChangesInternal(this._lView[TVIEW], this._lView, this.context);
checkNoChangesInternal(this._lView[TVIEW], this._lView, this.context as unknown as {});
}
attachToViewContainerRef() {
+1 -1
View File
@@ -11,7 +11,7 @@ export function getNativeRequestAnimationFrame() {
let nativeRequestAnimationFrame: (callback: FrameRequestCallback) => number =
global['requestAnimationFrame'];
let nativeCancelAnimationFrame: (handle: number) => void = global['cancelAnimationFrame'];
if (typeof Zone !== 'undefined' && nativeRequestAnimationFrame && nativeCancelAnimationFrame) {
if (typeof Zone !== 'undefined' && nativeRequestAnimationFrame! && nativeCancelAnimationFrame!) {
// use unpatched version of requestAnimationFrame(native delegate) if possible
// to avoid another Change detection
const unpatchedRequestAnimationFrame =
+2 -2
View File
@@ -179,11 +179,11 @@ export class TemplateFixture extends BaseFixture {
/**
* Fixture for testing Components in a convenient way.
*/
export class ComponentFixture<T> extends BaseFixture {
export class ComponentFixture<T extends {}> extends BaseFixture {
component: T;
requestAnimationFrame: {(fn: () => void): void; flush(): void; queue: (() => void)[];};
constructor(private componentType: ComponentType<T>, opts: {
constructor(componentType: ComponentType<T>, opts: {
injector?: Injector,
sanitizer?: Sanitizer,
rendererFactory?: RendererFactory3,
+1 -1
View File
@@ -322,7 +322,7 @@ export class TestBedRender3 implements TestBed {
if (token as unknown === TestBedRender3) {
return this as any;
}
const UNDEFINED = {};
const UNDEFINED = {} as unknown as T;
const result = this.testModuleRef.injector.get(token, UNDEFINED, flags);
return result === UNDEFINED ? this.compiler.injector.get(token, notFoundValue, flags) as any :
result;
+1 -1
View File
@@ -57,7 +57,7 @@ abstract class OverrideResolver<T> implements Resolver<T> {
const isKnownType = annotation instanceof Directive || annotation instanceof Component ||
annotation instanceof Pipe || annotation instanceof NgModule;
if (isKnownType) {
return annotation instanceof this.type ? annotation as T : null;
return annotation instanceof this.type ? annotation as unknown as T : null;
}
}
return null;
@@ -377,10 +377,6 @@ describe('find references and rename locations', () => {
expect(refs.length).toBe(2);
assertTextSpans(refs, ['myInput']);
// Get the declaration by finding the reference that appears first in the template
refs.sort((a, b) => a.textSpan.start - b.textSpan.start);
expect(refs[0].isDefinition).toBe(true);
});
it('finds rename location in template', () => {
@@ -418,10 +414,6 @@ describe('find references and rename locations', () => {
expect(refs.length).toBe(2);
assertTextSpans(refs, ['myTemplate']);
assertFileNames(refs, ['app.html']);
// Get the declaration by finding the reference that appears first in the template
refs.sort((a, b) => a.textSpan.start - b.textSpan.start);
expect(refs[0].isDefinition).toBe(true);
});
it('finds rename location in template', () => {
@@ -599,10 +591,6 @@ describe('find references and rename locations', () => {
expect(refs.length).toBe(3);
assertFileNames(refs, ['template.ng.html']);
assertTextSpans(refs, ['hero']);
// Get the declaration by finding the reference that appears first in the template
refs.sort((a, b) => a.textSpan.start - b.textSpan.start);
expect(refs[0].isDefinition).toBe(true);
});
it('should find rename locations', () => {
@@ -637,10 +625,6 @@ describe('find references and rename locations', () => {
expect(refs.length).toBe(2);
assertFileNames(refs, ['app.ts']);
assertTextSpans(refs, ['iRef']);
// Get the declaration by finding the reference that appears first in the template
refs.sort((a, b) => a.textSpan.start - b.textSpan.start);
expect(refs[0].isDefinition).toBe(true);
});
it('should find rename locations', () => {
@@ -102,7 +102,10 @@ export class Project {
if (!this.buffers.has(projectFileName)) {
const fileName = absoluteFrom(`/${this.name}/${projectFileName}`);
let scriptInfo = this.tsProject.getScriptInfo(fileName);
this.projectService.openClientFile(fileName);
this.projectService.openClientFile(
// By attempting to open the file, the compiler is going to try to parse it as
// TS which will throw an error. We pass in JSX which is more permissive.
fileName, undefined, fileName.endsWith('.html') ? ts.ScriptKind.JSX : ts.ScriptKind.TS);
// Mark the project as dirty because the act of opening a file may result in the version
// changing since TypeScript will `switchToScriptVersionCache` when a file is opened.
// Note that this emulates what we have to do in the server/extension as well.
@@ -83,8 +83,8 @@ export function makeStateKey<T = void>(key: string): StateKey<T> {
*/
@Injectable()
export class TransferState {
private store: {[k: string]: {}|undefined} = {};
private onSerializeCallbacks: {[k: string]: () => {} | undefined} = {};
private store: {[k: string]: unknown|undefined} = {};
private onSerializeCallbacks: {[k: string]: () => unknown | undefined} = {};
/** @internal */
static init(initState: {}) {
+1 -1
View File
@@ -19,7 +19,7 @@
"mocha": "^9.0.0",
"mock-require": "3.0.3",
"promises-aplus-tests": "^2.1.2",
"typescript": "~4.6.2"
"typescript": "4.7.0-beta"
},
"scripts": {
"closuretest": "./scripts/closure/closure_compiler.sh",
+1 -1
View File
@@ -14,6 +14,6 @@
"zone.js": "file:../../../../dist/bin/packages/zone.js/npm_package"
},
"devDependencies": {
"typescript": "~4.6.2"
"typescript": "4.7.0-beta"
}
}
+4 -4
View File
@@ -4007,10 +4007,10 @@ typedarray-to-buffer@^3.1.5:
dependencies:
is-typedarray "^1.0.0"
typescript@~4.6.2:
version "4.6.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c"
integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==
typescript@4.7.0-beta:
version "4.7.0-beta"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.0-beta.tgz#15952f24d4177479ca3d19f09436ad8c69a30563"
integrity sha512-m+CNL8lzHyHDxYYDTI+pm5hw5/bufYVGan2bokPyJY/y9C/4W/PCWMtYZ0vV9fLXbEL57elMeoaz9Evxs8UQ+A==
unbox-primitive@^1.0.1:
version "1.0.2"