Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #8423: Remove undefined while getting the type of the first argument of then signature #8449

Merged
merged 3 commits into from
May 4, 2016
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13443,7 +13443,7 @@ namespace ts {
}

function getTypeOfFirstParameterOfSignature(signature: Signature) {
return getTypeAtPosition(signature, 0);
return getTypeWithFacts(getTypeAtPosition(signature, 0), TypeFacts.NEUndefined);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function is used in two places

  • when we get type of first parameter in the call signature of then
  • when we get type of first parameter in the onFulfilled callback.

Do we want to strip undefined in both places or just in the first one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well. i went back and forth on this, and then did not see a reason why not...
so we want to get T

then<U>(success?: (value: T) => U,...): IPromise<U>

the first takes care of the optionality of succes?, the second would remove the undefined if value was optional. the question is what is the promised type for this:

then<U>(success?: (value?: T) => U,...): IPromise<U>

is it T or T|undefined ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about cases like this:

declare function resolve1<T>(value: T): Promise<T>;
declare function resolve2<T>(value: T): Windows.Foundation.IPromise<T>;

async function f(x?: number) {
    let x1 = await resolve1(x);
    let x2 = await resolve2(x);
}

Currently type of x1 is number | undefined and x2 fails with error addressed by this PR.
With the fix type of x2 will be just number which will be inconsistent with type for x1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point. fixed. thanks

}

/**
Expand Down
14 changes: 9 additions & 5 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ namespace ts {
name: "out",
type: "string",
isFilePath: false, // This is intentionally broken to support compatability with existing tsconfig files
// for correct behaviour, please use outFile
// for correct behaviour, please use outFile
paramType: Diagnostics.FILE,
},
{
Expand Down Expand Up @@ -464,7 +464,7 @@ namespace ts {

/* @internal */
export function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]) {
const key = (value || "").trim().toLowerCase();
const key = trimString((value || "")).toLowerCase();
const map = opt.type;
if (hasProperty(map, key)) {
return map[key];
Expand All @@ -476,7 +476,7 @@ namespace ts {

/* @internal */
export function parseListTypeOption(opt: CommandLineOptionOfListType, value: string, errors: Diagnostic[]): (string | number)[] {
const values = (value || "").trim().split(",");
const values = trimString((value || "")).split(",");
switch (opt.element.type) {
case "number":
return ts.map(values, parseInt);
Expand Down Expand Up @@ -601,7 +601,7 @@ namespace ts {
* Read tsconfig.json file
* @param fileName The path to the config file
*/
export function readConfigFile(fileName: string, readFile: (path: string) => string): { config?: any; error?: Diagnostic } {
export function readConfigFile(fileName: string, readFile: (path: string) => string): { config?: any; error?: Diagnostic } {
let text = "";
try {
text = readFile(fileName);
Expand Down Expand Up @@ -775,7 +775,7 @@ namespace ts {
defaultOptions: CompilerOptions | TypingOptions, diagnosticMessage: DiagnosticMessage, errors: Diagnostic[]) {

if (!jsonOptions) {
return ;
return;
}

const optionNameMap = arrayToMap(optionDeclarations, opt => opt.name);
Expand Down Expand Up @@ -829,4 +829,8 @@ namespace ts {
function convertJsonOptionOfListType(option: CommandLineOptionOfListType, values: any[], basePath: string, errors: Diagnostic[]): any[] {
return filter(map(values, v => convertJsonOption(option.element, v, basePath, errors)), v => !!v);
}

function trimString(s: string) {
return typeof s.trim === "function" ? s.trim() : s.replace(/^[\s]+|[\s]+$/g, "");
}
}
33 changes: 33 additions & 0 deletions tests/baselines/reference/asyncFunctionsAndStrictNullChecks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//// [asyncFunctionsAndStrictNullChecks.ts]

declare namespace Windows.Foundation {
interface IPromise<TResult> {
then<U>(success?: (value: TResult) => IPromise<U>, error?: (error: any) => IPromise<U>, progress?: (progress: any) => void): IPromise<U>;
then<U>(success?: (value: TResult) => IPromise<U>, error?: (error: any) => U, progress?: (progress: any) => void): IPromise<U>;
then<U>(success?: (value: TResult) => U, error?: (error: any) => IPromise<U>, progress?: (progress: any) => void): IPromise<U>;
then<U>(success?: (value: TResult) => U, error?: (error: any) => U, progress?: (progress: any) => void): IPromise<U>;
done<U>(success?: (value: TResult) => any, error?: (error: any) => any, progress?: (progress: any) => void): void;

cancel(): void;
}
}

async function sample(promise: Windows.Foundation.IPromise<number>) {
var number = await promise;
}


//// [asyncFunctionsAndStrictNullChecks.js]
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments)).next());
});
};
function sample(promise) {
return __awaiter(this, void 0, void 0, function* () {
var number = yield promise;
});
}
102 changes: 102 additions & 0 deletions tests/baselines/reference/asyncFunctionsAndStrictNullChecks.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
=== tests/cases/compiler/asyncFunctionsAndStrictNullChecks.ts ===

declare namespace Windows.Foundation {
>Windows : Symbol(Windows, Decl(asyncFunctionsAndStrictNullChecks.ts, 0, 0))
>Foundation : Symbol(Foundation, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 26))

interface IPromise<TResult> {
>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38))
>TResult : Symbol(TResult, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 23))

then<U>(success?: (value: TResult) => IPromise<U>, error?: (error: any) => IPromise<U>, progress?: (progress: any) => void): IPromise<U>;
>then : Symbol(IPromise.then, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 33), Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 145), Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 135), Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 135))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 13))
>success : Symbol(success, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 16))
>value : Symbol(value, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 27))
>TResult : Symbol(TResult, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 23))
>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 13))
>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 58))
>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 68))
>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 13))
>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 95))
>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 108))
>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 13))

then<U>(success?: (value: TResult) => IPromise<U>, error?: (error: any) => U, progress?: (progress: any) => void): IPromise<U>;
>then : Symbol(IPromise.then, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 33), Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 145), Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 135), Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 135))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 13))
>success : Symbol(success, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 16))
>value : Symbol(value, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 27))
>TResult : Symbol(TResult, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 23))
>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 13))
>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 58))
>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 68))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 13))
>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 85))
>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 98))
>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 13))

then<U>(success?: (value: TResult) => U, error?: (error: any) => IPromise<U>, progress?: (progress: any) => void): IPromise<U>;
>then : Symbol(IPromise.then, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 33), Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 145), Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 135), Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 135))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 13))
>success : Symbol(success, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 16))
>value : Symbol(value, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 27))
>TResult : Symbol(TResult, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 23))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 13))
>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 48))
>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 58))
>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 13))
>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 85))
>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 98))
>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 13))

then<U>(success?: (value: TResult) => U, error?: (error: any) => U, progress?: (progress: any) => void): IPromise<U>;
>then : Symbol(IPromise.then, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 33), Decl(asyncFunctionsAndStrictNullChecks.ts, 3, 145), Decl(asyncFunctionsAndStrictNullChecks.ts, 4, 135), Decl(asyncFunctionsAndStrictNullChecks.ts, 5, 135))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 13))
>success : Symbol(success, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 16))
>value : Symbol(value, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 27))
>TResult : Symbol(TResult, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 23))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 13))
>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 48))
>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 58))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 13))
>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 75))
>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 88))
>IPromise : Symbol(IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 13))

done<U>(success?: (value: TResult) => any, error?: (error: any) => any, progress?: (progress: any) => void): void;
>done : Symbol(IPromise.done, Decl(asyncFunctionsAndStrictNullChecks.ts, 6, 125))
>U : Symbol(U, Decl(asyncFunctionsAndStrictNullChecks.ts, 7, 13))
>success : Symbol(success, Decl(asyncFunctionsAndStrictNullChecks.ts, 7, 16))
>value : Symbol(value, Decl(asyncFunctionsAndStrictNullChecks.ts, 7, 27))
>TResult : Symbol(TResult, Decl(asyncFunctionsAndStrictNullChecks.ts, 2, 23))
>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 7, 50))
>error : Symbol(error, Decl(asyncFunctionsAndStrictNullChecks.ts, 7, 60))
>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 7, 79))
>progress : Symbol(progress, Decl(asyncFunctionsAndStrictNullChecks.ts, 7, 92))

cancel(): void;
>cancel : Symbol(IPromise.cancel, Decl(asyncFunctionsAndStrictNullChecks.ts, 7, 122))
}
}

async function sample(promise: Windows.Foundation.IPromise<number>) {
>sample : Symbol(sample, Decl(asyncFunctionsAndStrictNullChecks.ts, 11, 1))
>promise : Symbol(promise, Decl(asyncFunctionsAndStrictNullChecks.ts, 13, 22))
>Windows : Symbol(Windows, Decl(asyncFunctionsAndStrictNullChecks.ts, 0, 0))
>Foundation : Symbol(Windows.Foundation, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 26))
>IPromise : Symbol(Windows.Foundation.IPromise, Decl(asyncFunctionsAndStrictNullChecks.ts, 1, 38))

var number = await promise;
>number : Symbol(number, Decl(asyncFunctionsAndStrictNullChecks.ts, 14, 7))
>promise : Symbol(promise, Decl(asyncFunctionsAndStrictNullChecks.ts, 13, 22))
}

103 changes: 103 additions & 0 deletions tests/baselines/reference/asyncFunctionsAndStrictNullChecks.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
=== tests/cases/compiler/asyncFunctionsAndStrictNullChecks.ts ===

declare namespace Windows.Foundation {
>Windows : any
>Foundation : any

interface IPromise<TResult> {
>IPromise : IPromise<TResult>
>TResult : TResult

then<U>(success?: (value: TResult) => IPromise<U>, error?: (error: any) => IPromise<U>, progress?: (progress: any) => void): IPromise<U>;
>then : { <U>(success?: ((value: TResult) => IPromise<U>) | undefined, error?: ((error: any) => IPromise<U>) | undefined, progress?: ((progress: any) => void) | undefined): IPromise<U>; <U>(success?: ((value: TResult) => IPromise<U>) | undefined, error?: ((error: any) => U) | undefined, progress?: ((progress: any) => void) | undefined): IPromise<U>; <U>(success?: ((value: TResult) => U) | undefined, error?: ((error: any) => IPromise<U>) | undefined, progress?: ((progress: any) => void) | undefined): IPromise<U>; <U>(success?: ((value: TResult) => U) | undefined, error?: ((error: any) => U) | undefined, progress?: ((progress: any) => void) | undefined): IPromise<U>; }
>U : U
>success : ((value: TResult) => IPromise<U>) | undefined
>value : TResult
>TResult : TResult
>IPromise : IPromise<TResult>
>U : U
>error : ((error: any) => IPromise<U>) | undefined
>error : any
>IPromise : IPromise<TResult>
>U : U
>progress : ((progress: any) => void) | undefined
>progress : any
>IPromise : IPromise<TResult>
>U : U

then<U>(success?: (value: TResult) => IPromise<U>, error?: (error: any) => U, progress?: (progress: any) => void): IPromise<U>;
>then : { <U>(success?: ((value: TResult) => IPromise<U>) | undefined, error?: ((error: any) => IPromise<U>) | undefined, progress?: ((progress: any) => void) | undefined): IPromise<U>; <U>(success?: ((value: TResult) => IPromise<U>) | undefined, error?: ((error: any) => U) | undefined, progress?: ((progress: any) => void) | undefined): IPromise<U>; <U>(success?: ((value: TResult) => U) | undefined, error?: ((error: any) => IPromise<U>) | undefined, progress?: ((progress: any) => void) | undefined): IPromise<U>; <U>(success?: ((value: TResult) => U) | undefined, error?: ((error: any) => U) | undefined, progress?: ((progress: any) => void) | undefined): IPromise<U>; }
>U : U
>success : ((value: TResult) => IPromise<U>) | undefined
>value : TResult
>TResult : TResult
>IPromise : IPromise<TResult>
>U : U
>error : ((error: any) => U) | undefined
>error : any
>U : U
>progress : ((progress: any) => void) | undefined
>progress : any
>IPromise : IPromise<TResult>
>U : U

then<U>(success?: (value: TResult) => U, error?: (error: any) => IPromise<U>, progress?: (progress: any) => void): IPromise<U>;
>then : { <U>(success?: ((value: TResult) => IPromise<U>) | undefined, error?: ((error: any) => IPromise<U>) | undefined, progress?: ((progress: any) => void) | undefined): IPromise<U>; <U>(success?: ((value: TResult) => IPromise<U>) | undefined, error?: ((error: any) => U) | undefined, progress?: ((progress: any) => void) | undefined): IPromise<U>; <U>(success?: ((value: TResult) => U) | undefined, error?: ((error: any) => IPromise<U>) | undefined, progress?: ((progress: any) => void) | undefined): IPromise<U>; <U>(success?: ((value: TResult) => U) | undefined, error?: ((error: any) => U) | undefined, progress?: ((progress: any) => void) | undefined): IPromise<U>; }
>U : U
>success : ((value: TResult) => U) | undefined
>value : TResult
>TResult : TResult
>U : U
>error : ((error: any) => IPromise<U>) | undefined
>error : any
>IPromise : IPromise<TResult>
>U : U
>progress : ((progress: any) => void) | undefined
>progress : any
>IPromise : IPromise<TResult>
>U : U

then<U>(success?: (value: TResult) => U, error?: (error: any) => U, progress?: (progress: any) => void): IPromise<U>;
>then : { <U>(success?: ((value: TResult) => IPromise<U>) | undefined, error?: ((error: any) => IPromise<U>) | undefined, progress?: ((progress: any) => void) | undefined): IPromise<U>; <U>(success?: ((value: TResult) => IPromise<U>) | undefined, error?: ((error: any) => U) | undefined, progress?: ((progress: any) => void) | undefined): IPromise<U>; <U>(success?: ((value: TResult) => U) | undefined, error?: ((error: any) => IPromise<U>) | undefined, progress?: ((progress: any) => void) | undefined): IPromise<U>; <U>(success?: ((value: TResult) => U) | undefined, error?: ((error: any) => U) | undefined, progress?: ((progress: any) => void) | undefined): IPromise<U>; }
>U : U
>success : ((value: TResult) => U) | undefined
>value : TResult
>TResult : TResult
>U : U
>error : ((error: any) => U) | undefined
>error : any
>U : U
>progress : ((progress: any) => void) | undefined
>progress : any
>IPromise : IPromise<TResult>
>U : U

done<U>(success?: (value: TResult) => any, error?: (error: any) => any, progress?: (progress: any) => void): void;
>done : <U>(success?: ((value: TResult) => any) | undefined, error?: ((error: any) => any) | undefined, progress?: ((progress: any) => void) | undefined) => void
>U : U
>success : ((value: TResult) => any) | undefined
>value : TResult
>TResult : TResult
>error : ((error: any) => any) | undefined
>error : any
>progress : ((progress: any) => void) | undefined
>progress : any

cancel(): void;
>cancel : () => void
}
}

async function sample(promise: Windows.Foundation.IPromise<number>) {
>sample : (promise: Windows.Foundation.IPromise<number>) => Promise<void>
>promise : Windows.Foundation.IPromise<number>
>Windows : any
>Foundation : any
>IPromise : Windows.Foundation.IPromise<TResult>

var number = await promise;
>number : number
>await promise : number
>promise : Windows.Foundation.IPromise<number>
}

18 changes: 18 additions & 0 deletions tests/cases/compiler/asyncFunctionsAndStrictNullChecks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// @target: es6
// @strictNullChecks: true

declare namespace Windows.Foundation {
interface IPromise<TResult> {
then<U>(success?: (value: TResult) => IPromise<U>, error?: (error: any) => IPromise<U>, progress?: (progress: any) => void): IPromise<U>;
then<U>(success?: (value: TResult) => IPromise<U>, error?: (error: any) => U, progress?: (progress: any) => void): IPromise<U>;
then<U>(success?: (value: TResult) => U, error?: (error: any) => IPromise<U>, progress?: (progress: any) => void): IPromise<U>;
then<U>(success?: (value: TResult) => U, error?: (error: any) => U, progress?: (progress: any) => void): IPromise<U>;
done<U>(success?: (value: TResult) => any, error?: (error: any) => any, progress?: (progress: any) => void): void;

cancel(): void;
}
}

async function sample(promise: Windows.Foundation.IPromise<number>) {
var number = await promise;
}