Skip to content
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
11 changes: 6 additions & 5 deletions pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
Thank you for submitting a pull request!
Copy link
Member

Choose a reason for hiding this comment

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

I don’t think this file was supposed to be part of the PR.


Here's a checklist you might find useful.
[ ] There is an associated issue that is labelled
[X] There is an associated issue that is labelled
'Bug' or 'help wanted' or is in the Community milestone
[ ] Code is up-to-date with the `master` branch
[ ] You've successfully run `jake runtests` locally
[ ] You've signed the CLA
[ ] There are new or updated unit tests validating the change
[X] Code is up-to-date with the `master` branch
[X] You've successfully run `jake runtests` locally
[X] You've signed the CLA
[X] There are new or updated unit tests validating the change

Refer to CONTRIBUTING.MD for more details.
https://github.com/Microsoft/TypeScript/blob/master/CONTRIBUTING.md
-->

Fixes #
#17080
2 changes: 1 addition & 1 deletion src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13046,7 +13046,7 @@ namespace ts {
node.parent.kind === SyntaxKind.NonNullExpression ||
declaration.kind === SyntaxKind.VariableDeclaration && (<VariableDeclaration>declaration).exclamationToken ||
declaration.flags & NodeFlags.Ambient;
const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, getRootDeclaration(declaration) as VariableLikeDeclaration) : type) :
const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, declaration as VariableLikeDeclaration) : type) :
Copy link
Member

Choose a reason for hiding this comment

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

Any idea why getRootDeclaration was here? Was this copied from some other source that would also have an erroneous call to it?

Copy link
Member

Choose a reason for hiding this comment

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

I tracked it back to #14498, which switched to the current narrowing approach that this PR fixes. From my memory of it, I think that I inserted getRootDeclaration during development, then forgot to remove it after changing other parts of the code. Then none of our test cases caught the bug.

type === autoType || type === autoArrayType ? undefinedType :
getOptionalType(type);
const flowType = getFlowTypeOfReference(node, type, initialType, flowContainer, !assumeInitialized);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
tests/cases/compiler/optionalParameterInDestructuringWithInitializer.ts(6,8): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
Type 'undefined' is not assignable to type 'number'.
tests/cases/compiler/optionalParameterInDestructuringWithInitializer.ts(16,7): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
Type 'undefined' is not assignable to type 'number'.
tests/cases/compiler/optionalParameterInDestructuringWithInitializer.ts(21,7): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
Type 'undefined' is not assignable to type 'number'.
tests/cases/compiler/optionalParameterInDestructuringWithInitializer.ts(31,8): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
Type 'undefined' is not assignable to type 'number'.
tests/cases/compiler/optionalParameterInDestructuringWithInitializer.ts(45,10): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
Type 'undefined' is not assignable to type 'number'.
tests/cases/compiler/optionalParameterInDestructuringWithInitializer.ts(55,11): error TS2345: Argument of type 'number | null' is not assignable to parameter of type 'number | undefined'.
Type 'null' is not assignable to type 'number | undefined'.


==== tests/cases/compiler/optionalParameterInDestructuringWithInitializer.ts (6 errors) ====
// https://github.com/Microsoft/TypeScript/issues/17080
function f(a:number,b:number) {
}

function func1( {a, b}: {a: number, b?: number} = {a: 1, b: 2} ) {
f(a, b)
~
!!! error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
!!! error TS2345: Type 'undefined' is not assignable to type 'number'.
// error
}

function func2( {a, b = 3}: {a: number, b?:number} = {a: 1,b: 2} ) {
f(a, b)
// no error
}

function func3( {a, b}: {a: number, b?: number} = {a: 1} ) {
f(a,b)
~
!!! error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
!!! error TS2345: Type 'undefined' is not assignable to type 'number'.
// error
}

function func4( {a: {b, c}, d}: {a: {b: number,c?: number},d: number} = {a: {b: 1,c: 2},d: 3} ) {
f(b,c)
~
!!! error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
!!! error TS2345: Type 'undefined' is not assignable to type 'number'.
// error
}

function func5({a: {b, c = 4}, d}: {a: {b: number,c?: number},d: number} = {a: {b: 1,c: 2},d: 3} ) {
f(b, c)
// no error
}

function func6( {a: {b, c} = {b: 4, c: 5}, d}: {a: {b: number, c?: number}, d: number} = {a: {b: 1,c: 2}, d: 3} ) {
f(b, c)
~
!!! error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
!!! error TS2345: Type 'undefined' is not assignable to type 'number'.
// error
}

function func7( {a: {b, c = 6} = {b: 4, c: 5}, d}: {a: {b: number, c?: number}, d: number} = {a: {b: 1, c: 2}, d: 3} ) {
f(b, c)
// no error
}

interface Foo {
readonly bar?: number;
}

function performFoo({ bar }: Foo = {}) {
useBar(bar);
~~~
!!! error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'.
!!! error TS2345: Type 'undefined' is not assignable to type 'number'.
}

function useBar(bar: number) {
f(bar, 1)
}

performFoo();

function performFoo2({ bar = null }: Foo = {}) {
useBar2(bar);
~~~
!!! error TS2345: Argument of type 'number | null' is not assignable to parameter of type 'number | undefined'.
!!! error TS2345: Type 'null' is not assignable to type 'number | undefined'.
}

function useBar2(bar: number | undefined) {
if (bar) {
f(bar, 1)
}
}

performFoo2();

Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
//// [optionalParameterInDestructuringWithInitializer.ts]
// https://github.com/Microsoft/TypeScript/issues/17080
function f(a:number,b:number) {
}

function func1( {a, b}: {a: number, b?: number} = {a: 1, b: 2} ) {
f(a, b)
// error
}

function func2( {a, b = 3}: {a: number, b?:number} = {a: 1,b: 2} ) {
f(a, b)
// no error
}

function func3( {a, b}: {a: number, b?: number} = {a: 1} ) {
f(a,b)
// error
}

function func4( {a: {b, c}, d}: {a: {b: number,c?: number},d: number} = {a: {b: 1,c: 2},d: 3} ) {
f(b,c)
// error
}

function func5({a: {b, c = 4}, d}: {a: {b: number,c?: number},d: number} = {a: {b: 1,c: 2},d: 3} ) {
f(b, c)
// no error
}

function func6( {a: {b, c} = {b: 4, c: 5}, d}: {a: {b: number, c?: number}, d: number} = {a: {b: 1,c: 2}, d: 3} ) {
f(b, c)
// error
}

function func7( {a: {b, c = 6} = {b: 4, c: 5}, d}: {a: {b: number, c?: number}, d: number} = {a: {b: 1, c: 2}, d: 3} ) {
f(b, c)
// no error
}

interface Foo {
readonly bar?: number;
}

function performFoo({ bar }: Foo = {}) {
useBar(bar);
}

function useBar(bar: number) {
f(bar, 1)
}

performFoo();

function performFoo2({ bar = null }: Foo = {}) {
useBar2(bar);
}

function useBar2(bar: number | undefined) {
if (bar) {
f(bar, 1)
}
}

performFoo2();


//// [optionalParameterInDestructuringWithInitializer.js]
// https://github.com/Microsoft/TypeScript/issues/17080
function f(a, b) {
}
function func1(_a) {
var _b = _a === void 0 ? { a: 1, b: 2 } : _a, a = _b.a, b = _b.b;
f(a, b);
// error
}
function func2(_a) {
var _b = _a === void 0 ? { a: 1, b: 2 } : _a, a = _b.a, _c = _b.b, b = _c === void 0 ? 3 : _c;
f(a, b);
// no error
}
function func3(_a) {
var _b = _a === void 0 ? { a: 1 } : _a, a = _b.a, b = _b.b;
f(a, b);
// error
}
function func4(_a) {
var _b = _a === void 0 ? { a: { b: 1, c: 2 }, d: 3 } : _a, _c = _b.a, b = _c.b, c = _c.c, d = _b.d;
f(b, c);
// error
}
function func5(_a) {
var _b = _a === void 0 ? { a: { b: 1, c: 2 }, d: 3 } : _a, _c = _b.a, b = _c.b, _d = _c.c, c = _d === void 0 ? 4 : _d, d = _b.d;
f(b, c);
// no error
}
function func6(_a) {
var _b = _a === void 0 ? { a: { b: 1, c: 2 }, d: 3 } : _a, _c = _b.a, _d = _c === void 0 ? { b: 4, c: 5 } : _c, b = _d.b, c = _d.c, d = _b.d;
f(b, c);
// error
}
function func7(_a) {
var _b = _a === void 0 ? { a: { b: 1, c: 2 }, d: 3 } : _a, _c = _b.a, _d = _c === void 0 ? { b: 4, c: 5 } : _c, b = _d.b, _e = _d.c, c = _e === void 0 ? 6 : _e, d = _b.d;
f(b, c);
// no error
}
function performFoo(_a) {
var bar = (_a === void 0 ? {} : _a).bar;
useBar(bar);
}
function useBar(bar) {
f(bar, 1);
}
performFoo();
function performFoo2(_a) {
var _b = (_a === void 0 ? {} : _a).bar, bar = _b === void 0 ? null : _b;
useBar2(bar);
}
function useBar2(bar) {
if (bar) {
f(bar, 1);
}
}
performFoo2();
Loading