build: ts-api-guardian should support interface with value types (#27223)

This fixes an issue where a value would hide the type.

```
export interface Foo {
  someMethod(): void;
}

export const Foo: Function = ...;
```

In the above example the `Foo` constant will hide the `interface Foo` symbol.
This change properly saves the interface in addition to the type.

PR Close #27223
This commit is contained in:
Miško Hevery 2018-11-26 14:44:45 -08:00 committed by Jason Aden
parent 23b06af940
commit 60e403bf6d
10 changed files with 252 additions and 139 deletions

View File

@ -50,7 +50,7 @@ export const ANALYZE_FOR_ENTRY_COMPONENTS = new InjectionToken<any>('AnalyzeForE
/** /**
* Type of the Attribute decorator / constructor function. * Type of the Attribute decorator / constructor function.
* *
* * @publicApi
*/ */
export interface AttributeDecorator { export interface AttributeDecorator {
/** /**
@ -99,6 +99,8 @@ export interface AttributeDecorator {
/** /**
* Type of the Attribute metadata. * Type of the Attribute metadata.
*
* @publicApi
*/ */
export interface Attribute { attributeName?: string; } export interface Attribute { attributeName?: string; }
@ -113,6 +115,8 @@ export const Attribute: AttributeDecorator =
/** /**
* Type of the Query metadata. * Type of the Query metadata.
*
* @publicApi
*/ */
export interface Query { export interface Query {
descendants: boolean; descendants: boolean;
@ -181,6 +185,7 @@ export interface ContentChildrenDecorator {
* *
* *
* @Annotation * @Annotation
* @publicApi
*/ */
export type ContentChildren = Query; export type ContentChildren = Query;
@ -237,7 +242,7 @@ export interface ContentChildDecorator {
* *
* @see `ContentChild`. * @see `ContentChild`.
* *
* * @publicApi
*/ */
export type ContentChild = Query; export type ContentChild = Query;
@ -246,6 +251,7 @@ export type ContentChild = Query;
* *
* *
* @Annotation * @Annotation
*
* @publicApi * @publicApi
*/ */
export const ContentChild: ContentChildDecorator = makePropDecorator( export const ContentChild: ContentChildDecorator = makePropDecorator(
@ -293,6 +299,8 @@ export interface ViewChildrenDecorator {
/** /**
* Type of the ViewChildren metadata. * Type of the ViewChildren metadata.
*
* @publicApi
*/ */
export type ViewChildren = Query; export type ViewChildren = Query;
@ -359,6 +367,8 @@ export interface ViewChildDecorator {
/** /**
* Type of the ViewChild metadata. * Type of the ViewChild metadata.
*
* @publicApi
*/ */
export type ViewChild = Query; export type ViewChild = Query;

View File

@ -77,23 +77,31 @@ export interface DirectiveDecorator {
new (obj: Directive): Directive; new (obj: Directive): Directive;
} }
/**
* Directive decorator and metadata.
*
* @Annotation
* @publicApi
*/
export interface Directive { export interface Directive {
/** /**
* The CSS selector that triggers the instantiation of a directive. * The CSS selector that identifies this directive in a template
* and triggers instantiation of the directive.
* *
* Declare as one of the following: * Declare as one of the following:
* *
* - `element-name`: select by element name. * - `element-name`: Select by element name.
* - `.class`: select by class name. * - `.class`: Select by class name.
* - `[attribute]`: select by attribute name. * - `[attribute]`: Select by attribute name.
* - `[attribute=value]`: select by attribute name and value. * - `[attribute=value]`: Select by attribute name and value.
* - `:not(sub_selector)`: select only if the element does not match the `sub_selector`. * - `:not(sub_selector)`: Select only if the element does not match the `sub_selector`.
* - `selector1, selector2`: select if either `selector1` or `selector2` matches. * - `selector1, selector2`: Select if either `selector1` or `selector2` matches.
* *
* Angular only allows directives to trigger on CSS selectors that do not cross element * Angular only allows directives to apply on CSS selectors that do not cross
* boundaries. For example, consider a directive with an `input[type=text]` selector. * element boundaries.
* For the following HTML, the directive is instantiated only on the *
* `<input type="text">` element. * For the following template HTML, a directive with an `input[type=text]` selector,
* would be instantiated only on the `<input type="text">` element.
* *
* ```html * ```html
* <form> * <form>
@ -176,8 +184,9 @@ export interface Directive {
outputs?: string[]; outputs?: string[];
/** /**
* A set of injection tokens that allow the DI system to * Configures the [injector](guide/glossary#injector) of this
* provide a dependency to this directive or component. * directive or component with a [token](guide/glossary#di-token)
* that maps to a [provider](guide/glossary#provider) of a dependency.
*/ */
providers?: Provider[]; providers?: Provider[];
@ -247,62 +256,6 @@ export interface Directive {
*/ */
queries?: {[key: string]: any}; queries?: {[key: string]: any};
/**
* If true, this directive/component will be skipped by the AOT compiler and so will always be
* compiled using JIT.
*
* This exists to support future Ivy work and has no effect currently.
*/
jit?: true;
}
/**
* Directive decorator and metadata.
*
* @Annotation
*/
export interface Directive {
/**
* The CSS selector that identifies this directive in a template
* and triggers instantiation of the directive.
*
* Declare as one of the following:
*
* - `element-name`: Select by element name.
* - `.class`: Select by class name.
* - `[attribute]`: Select by attribute name.
* - `[attribute=value]`: Select by attribute name and value.
* - `:not(sub_selector)`: Select only if the element does not match the `sub_selector`.
* - `selector1, selector2`: Select if either `selector1` or `selector2` matches.
*
* Angular only allows directives to apply on CSS selectors that do not cross
* element boundaries.
*
* For the following template HTML, a directive with an `input[type=text]` selector,
* would be instantiated only on the `<input type="text">` element.
*
* ```html
* <form>
* <input type="text">
* <input type="radio">
* <form>
* ```
*
*/
selector?: string;
/**
* The set of event-bound output properties.
* When an output property emits an event, an event handler attached
* to that event in the template is invoked.
*
* Each output property maps a `directiveProperty` to a `bindingProperty`:
* - `directiveProperty` specifies the component property that emits events.
* - `bindingProperty` specifies the HTML attribute the event handler is attached to.
*
*/
outputs?: string[];
/** /**
* Maps class properties to host element bindings for properties, * Maps class properties to host element bindings for properties,
* attributes, and events, using a set of key-value pairs. * attributes, and events, using a set of key-value pairs.
@ -328,27 +281,12 @@ export interface Directive {
host?: {[key: string]: string}; host?: {[key: string]: string};
/** /**
* Configures the [injector](guide/glossary#injector) of this * If true, this directive/component will be skipped by the AOT compiler and so will always be
* directive or component with a [token](guide/glossary#di-token) * compiled using JIT.
* that maps to a [provider](guide/glossary#provider) of a dependency.
*/
providers?: Provider[];
/**
* The name or names that can be used in the template to assign this directive to a variable.
* For multiple names, use a comma-separated string.
* *
* This exists to support future Ivy work and has no effect currently.
*/ */
exportAs?: string; jit?: true;
/**
* Configures the queries that will be injected into the directive.
*
* Content queries are set before the `ngAfterContentInit` callback is called.
* View queries are set before the `ngAfterViewInit` callback is called.
*
*/
queries?: {[key: string]: any};
} }
/** /**
@ -512,6 +450,8 @@ export interface ComponentDecorator {
/** /**
* Supplies configuration metadata for an Angular component. * Supplies configuration metadata for an Angular component.
*
* @publicApi
*/ */
export interface Component extends Directive { export interface Component extends Directive {
/** /**
@ -645,6 +585,8 @@ export interface PipeDecorator {
/** /**
* Type of the Pipe metadata. * Type of the Pipe metadata.
*
* @publicApi
*/ */
export interface Pipe { export interface Pipe {
/** /**
@ -704,7 +646,7 @@ export interface InputDecorator {
/** /**
* Type of metadata for an `Input` property. * Type of metadata for an `Input` property.
* *
* * @publicApi
*/ */
export interface Input { export interface Input {
/** /**
@ -824,6 +766,8 @@ export interface OutputDecorator {
/** /**
* Type of the Output metadata. * Type of the Output metadata.
*
* @publicApi
*/ */
export interface Output { bindingPropertyName?: string; } export interface Output { bindingPropertyName?: string; }
@ -879,6 +823,7 @@ export interface HostBindingDecorator {
/** /**
* Type of the HostBinding metadata. * Type of the HostBinding metadata.
* *
* @publicApi
*/ */
export interface HostBinding { hostPropertyName?: string; } export interface HostBinding { hostPropertyName?: string; }
@ -902,6 +847,8 @@ export interface HostListenerDecorator {
/** /**
* Type of the HostListener metadata. * Type of the HostListener metadata.
*
* @publicApi
*/ */
export interface HostListener { export interface HostListener {
/** /**

View File

@ -127,6 +127,8 @@ export interface NgModuleDecorator {
/** /**
* Type of the NgModule metadata. * Type of the NgModule metadata.
*
* @publicApi
*/ */
export interface NgModule { export interface NgModule {
/** /**

View File

@ -20,6 +20,9 @@ const UNDEFINED = new Object();
let _nextRootElementId = 0; let _nextRootElementId = 0;
/**
* @publicApi
*/
export interface TestBed { export interface TestBed {
platform: PlatformRef; platform: PlatformRef;
@ -35,16 +38,12 @@ export interface TestBed {
* *
* Test modules and platforms for individual platforms are available from * Test modules and platforms for individual platforms are available from
* '@angular/<platform_name>/testing'. * '@angular/<platform_name>/testing'.
*
* @publicApi
*/ */
initTestEnvironment( initTestEnvironment(
ngModule: Type<any>|Type<any>[], platform: PlatformRef, aotSummaries?: () => any[]): void; ngModule: Type<any>|Type<any>[], platform: PlatformRef, aotSummaries?: () => any[]): void;
/** /**
* Reset the providers for the test injector. * Reset the providers for the test injector.
*
* @publicApi
*/ */
resetTestEnvironment(): void; resetTestEnvironment(): void;
@ -119,8 +118,6 @@ export class TestBedViewEngine implements Injector, TestBed {
* *
* Test modules and platforms for individual platforms are available from * Test modules and platforms for individual platforms are available from
* '@angular/<platform_name>/testing'. * '@angular/<platform_name>/testing'.
*
* @publicApi
*/ */
static initTestEnvironment( static initTestEnvironment(
ngModule: Type<any>|Type<any>[], platform: PlatformRef, ngModule: Type<any>|Type<any>[], platform: PlatformRef,
@ -132,8 +129,6 @@ export class TestBedViewEngine implements Injector, TestBed {
/** /**
* Reset the providers for the test injector. * Reset the providers for the test injector.
*
* @publicApi
*/ */
static resetTestEnvironment(): void { _getTestBedViewEngine().resetTestEnvironment(); } static resetTestEnvironment(): void { _getTestBedViewEngine().resetTestEnvironment(); }
@ -291,8 +286,6 @@ export class TestBedViewEngine implements Injector, TestBed {
* *
* Test modules and platforms for individual platforms are available from * Test modules and platforms for individual platforms are available from
* '@angular/<platform_name>/testing'. * '@angular/<platform_name>/testing'.
*
* @publicApi
*/ */
initTestEnvironment( initTestEnvironment(
ngModule: Type<any>|Type<any>[], platform: PlatformRef, aotSummaries?: () => any[]): void { ngModule: Type<any>|Type<any>[], platform: PlatformRef, aotSummaries?: () => any[]): void {
@ -308,8 +301,6 @@ export class TestBedViewEngine implements Injector, TestBed {
/** /**
* Reset the providers for the test injector. * Reset the providers for the test injector.
*
* @publicApi
*/ */
resetTestEnvironment(): void { resetTestEnvironment(): void {
this.resetTestingModule(); this.resetTestingModule();

View File

@ -47,6 +47,10 @@ export declare function asNativeElements(debugEls: DebugElement[]): any;
export declare function assertPlatform(requiredToken: any): PlatformRef; export declare function assertPlatform(requiredToken: any): PlatformRef;
export interface Attribute {
attributeName?: string;
}
export declare const Attribute: AttributeDecorator; export declare const Attribute: AttributeDecorator;
export declare enum ChangeDetectionStrategy { export declare enum ChangeDetectionStrategy {
@ -95,6 +99,21 @@ export declare type CompilerOptions = {
preserveWhitespaces?: boolean; preserveWhitespaces?: boolean;
}; };
export interface Component extends Directive {
animations?: any[];
changeDetection?: ChangeDetectionStrategy;
encapsulation?: ViewEncapsulation;
entryComponents?: Array<Type<any> | any[]>;
interpolation?: [string, string];
moduleId?: string;
preserveWhitespaces?: boolean;
styleUrls?: string[];
styles?: string[];
template?: string;
templateUrl?: string;
viewProviders?: Provider[];
}
export declare const Component: ComponentDecorator; export declare const Component: ComponentDecorator;
export interface ComponentDecorator { export interface ComponentDecorator {
@ -137,7 +156,7 @@ export interface ConstructorSansProvider {
deps?: any[]; deps?: any[];
} }
export declare const ContentChild: ContentChildDecorator; export declare type ContentChild = Query;
export interface ContentChildDecorator { export interface ContentChildDecorator {
(selector: Type<any> | Function | string, opts?: { (selector: Type<any> | Function | string, opts?: {
@ -148,7 +167,7 @@ export interface ContentChildDecorator {
}): ContentChild; }): ContentChild;
} }
export declare const ContentChildren: ContentChildrenDecorator; export declare type ContentChildren = Query;
export interface ContentChildrenDecorator { export interface ContentChildrenDecorator {
(selector: Type<any> | Function | string, opts?: { (selector: Type<any> | Function | string, opts?: {
@ -242,6 +261,21 @@ export declare function defineInjector(options: {
export declare function destroyPlatform(): void; export declare function destroyPlatform(): void;
export interface Directive {
exportAs?: string;
host?: {
[key: string]: string;
};
inputs?: string[];
jit?: true;
outputs?: string[];
providers?: Provider[];
queries?: {
[key: string]: any;
};
selector?: string;
}
export declare const Directive: DirectiveDecorator; export declare const Directive: DirectiveDecorator;
export interface DirectiveDecorator { export interface DirectiveDecorator {
@ -307,8 +341,15 @@ export interface GetTestability {
findTestabilityInTree(registry: TestabilityRegistry, elem: any, findInAncestors: boolean): Testability | null; findTestabilityInTree(registry: TestabilityRegistry, elem: any, findInAncestors: boolean): Testability | null;
} }
export interface Host {
}
export declare const Host: HostDecorator; export declare const Host: HostDecorator;
export interface HostBinding {
hostPropertyName?: string;
}
export declare const HostBinding: HostBindingDecorator; export declare const HostBinding: HostBindingDecorator;
export interface HostDecorator { export interface HostDecorator {
@ -316,13 +357,26 @@ export interface HostDecorator {
new (): Host; new (): Host;
} }
export interface HostListener {
args?: string[];
eventName?: string;
}
export declare const HostListener: HostListenerDecorator; export declare const HostListener: HostListenerDecorator;
export declare function inject<T>(token: Type<T> | InjectionToken<T>): T; export declare function inject<T>(token: Type<T> | InjectionToken<T>): T;
export declare function inject<T>(token: Type<T> | InjectionToken<T>, flags?: InjectFlags): T | null; export declare function inject<T>(token: Type<T> | InjectionToken<T>, flags?: InjectFlags): T | null;
export interface Inject {
token: any;
}
export declare const Inject: InjectDecorator; export declare const Inject: InjectDecorator;
export interface Injectable {
providedIn?: Type<any> | 'root' | null;
}
export declare const Injectable: InjectableDecorator; export declare const Injectable: InjectableDecorator;
export interface InjectableDecorator { export interface InjectableDecorator {
@ -385,6 +439,10 @@ export interface InjectorType<T> extends Type<T> {
ngInjectorDef: never; ngInjectorDef: never;
} }
export interface Input {
bindingPropertyName?: string;
}
export declare const Input: InputDecorator; export declare const Input: InputDecorator;
export declare function isDevMode(): boolean; export declare function isDevMode(): boolean;
@ -480,6 +538,18 @@ export interface ModuleWithProviders<T = any /** TODO(alxhub): remove default wh
export declare type NgIterable<T> = Array<T> | Iterable<T>; export declare type NgIterable<T> = Array<T> | Iterable<T>;
export interface NgModule {
bootstrap?: Array<Type<any> | any[]>;
declarations?: Array<Type<any> | any[]>;
entryComponents?: Array<Type<any> | any[]>;
exports?: Array<Type<any> | any[]>;
id?: string;
imports?: Array<Type<any> | ModuleWithProviders<{}> | any[]>;
jit?: true;
providers?: Provider[];
schemas?: Array<SchemaMetadata | any[]>;
}
export declare const NgModule: NgModuleDecorator; export declare const NgModule: NgModuleDecorator;
export declare abstract class NgModuleFactory<T> { export declare abstract class NgModuleFactory<T> {
@ -539,6 +609,9 @@ export interface OnInit {
ngOnInit(): void; ngOnInit(): void;
} }
export interface Optional {
}
export declare const Optional: OptionalDecorator; export declare const Optional: OptionalDecorator;
export interface OptionalDecorator { export interface OptionalDecorator {
@ -546,10 +619,19 @@ export interface OptionalDecorator {
new (): Optional; new (): Optional;
} }
export interface Output {
bindingPropertyName?: string;
}
export declare const Output: OutputDecorator; export declare const Output: OutputDecorator;
export declare const PACKAGE_ROOT_URL: InjectionToken<string>; export declare const PACKAGE_ROOT_URL: InjectionToken<string>;
export interface Pipe {
name: string;
pure?: boolean;
}
export declare const Pipe: PipeDecorator; export declare const Pipe: PipeDecorator;
export interface PipeTransform { export interface PipeTransform {
@ -577,6 +659,14 @@ export interface Predicate<T> {
export declare type Provider = TypeProvider | ValueProvider | ClassProvider | ConstructorProvider | ExistingProvider | FactoryProvider | any[]; export declare type Provider = TypeProvider | ValueProvider | ClassProvider | ConstructorProvider | ExistingProvider | FactoryProvider | any[];
export interface Query {
descendants: boolean;
first: boolean;
isViewQuery: boolean;
read: any;
selector: any;
}
export declare abstract class Query { export declare abstract class Query {
} }
@ -742,6 +832,9 @@ export declare enum SecurityContext {
RESOURCE_URL = 5 RESOURCE_URL = 5
} }
export interface Self {
}
export declare const Self: SelfDecorator; export declare const Self: SelfDecorator;
export interface SelfDecorator { export interface SelfDecorator {
@ -763,6 +856,9 @@ export interface SimpleChanges {
[propName: string]: SimpleChange; [propName: string]: SimpleChange;
} }
export interface SkipSelf {
}
export declare const SkipSelf: SkipSelfDecorator; export declare const SkipSelf: SkipSelfDecorator;
export interface SkipSelfDecorator { export interface SkipSelfDecorator {
@ -841,7 +937,7 @@ export declare class Version {
export declare const VERSION: Version; export declare const VERSION: Version;
export declare const ViewChild: ViewChildDecorator; export declare type ViewChild = Query;
export interface ViewChildDecorator { export interface ViewChildDecorator {
(selector: Type<any> | Function | string, opts?: { (selector: Type<any> | Function | string, opts?: {
@ -852,7 +948,7 @@ export interface ViewChildDecorator {
}): ViewChild; }): ViewChild;
} }
export declare const ViewChildren: ViewChildrenDecorator; export declare type ViewChildren = Query;
export interface ViewChildrenDecorator { export interface ViewChildrenDecorator {
(selector: Type<any> | Function | string, opts?: { (selector: Type<any> | Function | string, opts?: {

View File

@ -47,6 +47,52 @@ export declare type MetadataOverride<T> = {
export declare function resetFakeAsyncZone(): void; export declare function resetFakeAsyncZone(): void;
export interface TestBed {
ngModule: Type<any> | Type<any>[];
platform: PlatformRef;
compileComponents(): Promise<any>;
configureCompiler(config: {
providers?: any[];
useJit?: boolean;
}): void;
configureTestingModule(moduleDef: TestModuleMetadata): void;
createComponent<T>(component: Type<T>): ComponentFixture<T>;
deprecatedOverrideProvider(token: any, provider: {
useFactory?: Function;
useValue?: any;
deps?: any[];
}): void;
/** @deprecated */ deprecatedOverrideProvider(token: any, provider: {
useFactory: Function;
deps: any[];
}): void;
deprecatedOverrideProvider(token: any, provider: {
useValue: any;
}): void;
execute(tokens: any[], fn: Function, context?: any): any;
get(token: any, notFoundValue?: any): any;
initTestEnvironment(ngModule: Type<any> | Type<any>[], platform: PlatformRef, aotSummaries?: () => any[]): void;
overrideComponent(component: Type<any>, override: MetadataOverride<Component>): void;
overrideDirective(directive: Type<any>, override: MetadataOverride<Directive>): void;
overrideModule(ngModule: Type<any>, override: MetadataOverride<NgModule>): void;
overridePipe(pipe: Type<any>, override: MetadataOverride<Pipe>): void;
overrideProvider(token: any, provider: {
useFactory?: Function;
useValue?: any;
deps?: any[];
}): void;
overrideProvider(token: any, provider: {
useFactory: Function;
deps: any[];
}): void;
overrideProvider(token: any, provider: {
useValue: any;
}): void;
overrideTemplateUsingTestingModule(component: Type<any>, template: string): void;
resetTestEnvironment(): void;
resetTestingModule(): void;
}
export declare const TestBed: TestBedStatic; export declare const TestBed: TestBedStatic;
export interface TestBedStatic { export interface TestBedStatic {

View File

@ -115,7 +115,7 @@ class ResolvedDeclarationEmitter {
throw new Error(`Source file "${this.fileName}" not found`); throw new Error(`Source file "${this.fileName}" not found`);
} }
let output = ''; let output: string[] = [];
const resolvedSymbols = this.getResolvedSymbols(sourceFile); const resolvedSymbols = this.getResolvedSymbols(sourceFile);
// Sort all symbols so that the output is more deterministic // Sort all symbols so that the output is more deterministic
@ -126,42 +126,19 @@ class ResolvedDeclarationEmitter {
continue; continue;
} }
let decl: ts.Node|undefined = const typeDecl = symbol.declarations && symbol.declarations[0];
symbol.valueDeclaration || symbol.declarations && symbol.declarations[0]; const valDecl = symbol.valueDeclaration;
if (!decl) { if (!typeDecl && !valDecl) {
this.diagnostics.push({ this.diagnostics.push({
type: 'warn', type: 'warn',
message: `${sourceFile.fileName}: error: No declaration found for symbol "${symbol.name}"` message: `${sourceFile.fileName}: error: No declaration found for symbol "${symbol.name}"`
}); });
continue; continue;
} }
typeDecl && this.emitDeclaration(symbol, typeDecl, output);
// The declaration node may not be a complete statement, e.g. for var/const if (valDecl && typeDecl.kind === ts.SyntaxKind.InterfaceDeclaration) {
// symbols. We need to find the complete export statement by traversing // Only generate value declarations in case of interfaces.
// upwards. valDecl && this.emitDeclaration(symbol, valDecl, output);
while (!hasModifier(decl, ts.SyntaxKind.ExportKeyword) && decl.parent) {
decl = decl.parent;
}
if (hasModifier(decl, ts.SyntaxKind.ExportKeyword)) {
// Make an empty line between two exports
if (output) {
output += '\n';
}
const jsdocComment = this.processJsDocTags(decl, this.options.exportTags);
if (jsdocComment) {
output += jsdocComment + '\n';
}
output += stripEmptyLines(this.emitNode(decl)) + '\n';
} else {
// This may happen for symbols re-exported from external modules.
this.diagnostics.push({
type: 'warn',
message:
createErrorMessage(decl, `No export declaration found for symbol "${symbol.name}"`)
});
} }
} }
@ -173,7 +150,36 @@ class ResolvedDeclarationEmitter {
} }
} }
return output; return output.join('');
}
emitDeclaration(symbol: ts.Symbol, decl: ts.Node, output: string[]) {
// The declaration node may not be a complete statement, e.g. for var/const
// symbols. We need to find the complete export statement by traversing
// upwards.
while (!hasModifier(decl, ts.SyntaxKind.ExportKeyword) && decl.parent) {
decl = decl.parent;
}
if (hasModifier(decl, ts.SyntaxKind.ExportKeyword)) {
// Make an empty line between two exports
if (output.length) {
output.push('\n');
}
const jsdocComment = this.processJsDocTags(decl, this.options.exportTags);
if (jsdocComment) {
output.push(jsdocComment + '\n');
}
output.push(stripEmptyLines(this.emitNode(decl)) + '\n');
} else {
// This may happen for symbols re-exported from external modules.
this.diagnostics.push({
type: 'warn',
message: createErrorMessage(decl, `No export declaration found for symbol "${symbol.name}"`)
});
}
} }
private isExportPatternStripped(symbolName: string): boolean { private isExportPatternStripped(symbolName: string): boolean {

View File

@ -0,0 +1,4 @@
export interface TypeOnly { field: string; }
export interface TypeAndValue { field: string; }
export const TypeAndValue: Function;

View File

@ -0,0 +1,5 @@
export interface TypeAndValue { field: string; }
export const TypeAndValue: Function;
export interface TypeOnly { field: string; }

View File

@ -45,6 +45,12 @@ describe('integration test: public api', () => {
'test/fixtures/classes_and_interfaces_expected.d.ts'); 'test/fixtures/classes_and_interfaces_expected.d.ts');
}); });
it('should include value and type', () => {
check(
'test/fixtures/exports_type_and_value.d.ts',
'test/fixtures/exports_type_and_value_expected.d.ts');
});
it('should include members reexported classes', () => { it('should include members reexported classes', () => {
check( check(
'test/fixtures/reexported_classes.d.ts', 'test/fixtures/reexported_classes_expected.d.ts'); 'test/fixtures/reexported_classes.d.ts', 'test/fixtures/reexported_classes_expected.d.ts');