diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f5f82917b877b..74ca86a5e040f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -35659,8 +35659,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const functionFlags = getFunctionFlags(func); const type = returnType && unwrapReturnType(returnType, functionFlags); - // Functions with an explicitly specified 'undefined, 'void' or 'any' return type don't need any return expressions. - if (type && maybeTypeOfKind(type, TypeFlags.Undefined | TypeFlags.Void | TypeFlags.Any)) { + // Functions with an explicitly specified 'undefined, 'void', 'any' or 'unknown' return type don't need any return expressions. + if (type && maybeTypeOfKind(type, TypeFlags.Undefined | TypeFlags.Void | TypeFlags.Any | TypeFlags.Unknown)) { return; } diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).js b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).js new file mode 100644 index 0000000000000..13870dc02f148 --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).js @@ -0,0 +1,85 @@ +//// [functionsWithImplicitReturnTypeAssignableToUndefined.ts] +function f1(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is always assignable to unknown. +} + +type MyUnknown = unknown; +function f2(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is always assignable to unknown. +} + +function f3(): any { + // Implicit return, but undefined is always assignable to any. +} + +function f4(): void { + // Implicit return, but undefined is always assignable to void. +} + +function f5(): {} { + if (Math.random() < 0.5) return {}; + + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} + +function f6(): Record { + if (Math.random() < 0.5) return { "foo": true }; + + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} + +function f7(): null { + if (Math.random() < 0.5) return null; + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + +function f8(): string | null { + if (Math.random() < 0.5) return "foo"; + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + +//// [functionsWithImplicitReturnTypeAssignableToUndefined.js] +function f1() { + if (Math.random() < 0.5) + return true; + // Implicit return, but undefined is always assignable to unknown. +} +function f2() { + if (Math.random() < 0.5) + return true; + // Implicit return, but undefined is always assignable to unknown. +} +function f3() { + // Implicit return, but undefined is always assignable to any. +} +function f4() { + // Implicit return, but undefined is always assignable to void. +} +function f5() { + if (Math.random() < 0.5) + return {}; + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} +function f6() { + if (Math.random() < 0.5) + return { "foo": true }; + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} +function f7() { + if (Math.random() < 0.5) + return null; + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} +function f8() { + if (Math.random() < 0.5) + return "foo"; + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).symbols b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).symbols new file mode 100644 index 0000000000000..776d1aaaa0d53 --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).symbols @@ -0,0 +1,84 @@ +=== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts === +function f1(): unknown { +>f1 : Symbol(f1, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 0, 0)) + + if (Math.random() < 0.5) return true; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is always assignable to unknown. +} + +type MyUnknown = unknown; +>MyUnknown : Symbol(MyUnknown, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 4, 1)) + +function f2(): unknown { +>f2 : Symbol(f2, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 6, 25)) + + if (Math.random() < 0.5) return true; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is always assignable to unknown. +} + +function f3(): any { +>f3 : Symbol(f3, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 11, 1)) + + // Implicit return, but undefined is always assignable to any. +} + +function f4(): void { +>f4 : Symbol(f4, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 15, 1)) + + // Implicit return, but undefined is always assignable to void. +} + +function f5(): {} { +>f5 : Symbol(f5, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 19, 1)) + + if (Math.random() < 0.5) return {}; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} + +function f6(): Record { +>f6 : Symbol(f6, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 25, 1)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + + if (Math.random() < 0.5) return { "foo": true }; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>"foo" : Symbol("foo", Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 28, 37)) + + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} + +function f7(): null { +>f7 : Symbol(f7, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 32, 1)) + + if (Math.random() < 0.5) return null; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + +function f8(): string | null { +>f8 : Symbol(f8, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 38, 1)) + + if (Math.random() < 0.5) return "foo"; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).types b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).types new file mode 100644 index 0000000000000..d05f08c2bc427 --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=false).types @@ -0,0 +1,107 @@ +=== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts === +function f1(): unknown { +>f1 : () => unknown + + if (Math.random() < 0.5) return true; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>true : true + + // Implicit return, but undefined is always assignable to unknown. +} + +type MyUnknown = unknown; +>MyUnknown : unknown + +function f2(): unknown { +>f2 : () => unknown + + if (Math.random() < 0.5) return true; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>true : true + + // Implicit return, but undefined is always assignable to unknown. +} + +function f3(): any { +>f3 : () => any + + // Implicit return, but undefined is always assignable to any. +} + +function f4(): void { +>f4 : () => void + + // Implicit return, but undefined is always assignable to void. +} + +function f5(): {} { +>f5 : () => {} + + if (Math.random() < 0.5) return {}; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>{} : {} + + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} + +function f6(): Record { +>f6 : () => Record + + if (Math.random() < 0.5) return { "foo": true }; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>{ "foo": true } : { foo: boolean; } +>"foo" : boolean +>true : true + + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} + +function f7(): null { +>f7 : () => null + + if (Math.random() < 0.5) return null; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + +function f8(): string | null { +>f8 : () => string | null + + if (Math.random() < 0.5) return "foo"; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>"foo" : "foo" + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).errors.txt b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).errors.txt new file mode 100644 index 0000000000000..844cb5201977f --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).errors.txt @@ -0,0 +1,60 @@ +tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(22,16): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. +tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(28,16): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. +tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(35,16): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. +tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts(41,16): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. + + +==== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts (4 errors) ==== + function f1(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is always assignable to unknown. + } + + type MyUnknown = unknown; + function f2(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is always assignable to unknown. + } + + function f3(): any { + // Implicit return, but undefined is always assignable to any. + } + + function f4(): void { + // Implicit return, but undefined is always assignable to void. + } + + function f5(): {} { + ~~ +!!! error TS2366: Function lacks ending return statement and return type does not include 'undefined'. + if (Math.random() < 0.5) return {}; + + // Implicit return, but undefined is assignable to object when strictNullChecks is off. + } + + function f6(): Record { + ~~~~~~~~~~~~~~~~~~~ +!!! error TS2366: Function lacks ending return statement and return type does not include 'undefined'. + if (Math.random() < 0.5) return { "foo": true }; + + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. + } + + function f7(): null { + ~~~~ +!!! error TS2366: Function lacks ending return statement and return type does not include 'undefined'. + if (Math.random() < 0.5) return null; + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. + } + + function f8(): string | null { + ~~~~~~~~~~~~~ +!!! error TS2366: Function lacks ending return statement and return type does not include 'undefined'. + if (Math.random() < 0.5) return "foo"; + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. + } \ No newline at end of file diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).js b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).js new file mode 100644 index 0000000000000..13870dc02f148 --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).js @@ -0,0 +1,85 @@ +//// [functionsWithImplicitReturnTypeAssignableToUndefined.ts] +function f1(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is always assignable to unknown. +} + +type MyUnknown = unknown; +function f2(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is always assignable to unknown. +} + +function f3(): any { + // Implicit return, but undefined is always assignable to any. +} + +function f4(): void { + // Implicit return, but undefined is always assignable to void. +} + +function f5(): {} { + if (Math.random() < 0.5) return {}; + + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} + +function f6(): Record { + if (Math.random() < 0.5) return { "foo": true }; + + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} + +function f7(): null { + if (Math.random() < 0.5) return null; + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + +function f8(): string | null { + if (Math.random() < 0.5) return "foo"; + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + +//// [functionsWithImplicitReturnTypeAssignableToUndefined.js] +function f1() { + if (Math.random() < 0.5) + return true; + // Implicit return, but undefined is always assignable to unknown. +} +function f2() { + if (Math.random() < 0.5) + return true; + // Implicit return, but undefined is always assignable to unknown. +} +function f3() { + // Implicit return, but undefined is always assignable to any. +} +function f4() { + // Implicit return, but undefined is always assignable to void. +} +function f5() { + if (Math.random() < 0.5) + return {}; + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} +function f6() { + if (Math.random() < 0.5) + return { "foo": true }; + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} +function f7() { + if (Math.random() < 0.5) + return null; + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} +function f8() { + if (Math.random() < 0.5) + return "foo"; + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).symbols b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).symbols new file mode 100644 index 0000000000000..776d1aaaa0d53 --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).symbols @@ -0,0 +1,84 @@ +=== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts === +function f1(): unknown { +>f1 : Symbol(f1, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 0, 0)) + + if (Math.random() < 0.5) return true; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is always assignable to unknown. +} + +type MyUnknown = unknown; +>MyUnknown : Symbol(MyUnknown, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 4, 1)) + +function f2(): unknown { +>f2 : Symbol(f2, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 6, 25)) + + if (Math.random() < 0.5) return true; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is always assignable to unknown. +} + +function f3(): any { +>f3 : Symbol(f3, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 11, 1)) + + // Implicit return, but undefined is always assignable to any. +} + +function f4(): void { +>f4 : Symbol(f4, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 15, 1)) + + // Implicit return, but undefined is always assignable to void. +} + +function f5(): {} { +>f5 : Symbol(f5, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 19, 1)) + + if (Math.random() < 0.5) return {}; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} + +function f6(): Record { +>f6 : Symbol(f6, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 25, 1)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + + if (Math.random() < 0.5) return { "foo": true }; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>"foo" : Symbol("foo", Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 28, 37)) + + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} + +function f7(): null { +>f7 : Symbol(f7, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 32, 1)) + + if (Math.random() < 0.5) return null; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + +function f8(): string | null { +>f8 : Symbol(f8, Decl(functionsWithImplicitReturnTypeAssignableToUndefined.ts, 38, 1)) + + if (Math.random() < 0.5) return "foo"; +>Math.random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) +>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>random : Symbol(Math.random, Decl(lib.es5.d.ts, --, --)) + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} diff --git a/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).types b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).types new file mode 100644 index 0000000000000..d05f08c2bc427 --- /dev/null +++ b/tests/baselines/reference/functionsWithImplicitReturnTypeAssignableToUndefined(strictnullchecks=true).types @@ -0,0 +1,107 @@ +=== tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts === +function f1(): unknown { +>f1 : () => unknown + + if (Math.random() < 0.5) return true; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>true : true + + // Implicit return, but undefined is always assignable to unknown. +} + +type MyUnknown = unknown; +>MyUnknown : unknown + +function f2(): unknown { +>f2 : () => unknown + + if (Math.random() < 0.5) return true; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>true : true + + // Implicit return, but undefined is always assignable to unknown. +} + +function f3(): any { +>f3 : () => any + + // Implicit return, but undefined is always assignable to any. +} + +function f4(): void { +>f4 : () => void + + // Implicit return, but undefined is always assignable to void. +} + +function f5(): {} { +>f5 : () => {} + + if (Math.random() < 0.5) return {}; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>{} : {} + + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} + +function f6(): Record { +>f6 : () => Record + + if (Math.random() < 0.5) return { "foo": true }; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>{ "foo": true } : { foo: boolean; } +>"foo" : boolean +>true : true + + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} + +function f7(): null { +>f7 : () => null + + if (Math.random() < 0.5) return null; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + +function f8(): string | null { +>f8 : () => string | null + + if (Math.random() < 0.5) return "foo"; +>Math.random() < 0.5 : boolean +>Math.random() : number +>Math.random : () => number +>Math : Math +>random : () => number +>0.5 : 0.5 +>"foo" : "foo" + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} diff --git a/tests/baselines/reference/unknownType1.errors.txt b/tests/baselines/reference/unknownType1.errors.txt index 32034c8e2b9d9..f86564eb5ce8b 100644 --- a/tests/baselines/reference/unknownType1.errors.txt +++ b/tests/baselines/reference/unknownType1.errors.txt @@ -20,7 +20,6 @@ tests/cases/conformance/types/unknown/unknownType1.ts(128,5): error TS2322: Type tests/cases/conformance/types/unknown/unknownType1.ts(129,5): error TS2322: Type 'number' is not assignable to type '{ [x: string]: unknown; }'. tests/cases/conformance/types/unknown/unknownType1.ts(143,29): error TS2698: Spread types may only be created from object types. tests/cases/conformance/types/unknown/unknownType1.ts(144,29): error TS2698: Spread types may only be created from object types. -tests/cases/conformance/types/unknown/unknownType1.ts(150,17): error TS2847: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. tests/cases/conformance/types/unknown/unknownType1.ts(156,14): error TS2700: Rest types may only be created from object types. tests/cases/conformance/types/unknown/unknownType1.ts(162,5): error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor. tests/cases/conformance/types/unknown/unknownType1.ts(170,9): error TS2322: Type 'T' is not assignable to type '{}'. @@ -28,7 +27,7 @@ tests/cases/conformance/types/unknown/unknownType1.ts(171,9): error TS2322: Type tests/cases/conformance/types/unknown/unknownType1.ts(181,5): error TS2322: Type 'T' is not assignable to type '{}'. -==== tests/cases/conformance/types/unknown/unknownType1.ts (27 errors) ==== +==== tests/cases/conformance/types/unknown/unknownType1.ts (26 errors) ==== // In an intersection everything absorbs unknown type T00 = unknown & null; // null @@ -222,8 +221,6 @@ tests/cases/conformance/types/unknown/unknownType1.ts(181,5): error TS2322: Type // Functions with unknown return type don't need return expressions function f27(): unknown { - ~~~~~~~ -!!! error TS2847: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. } // Rest type cannot be created from unknown diff --git a/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts b/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts new file mode 100644 index 0000000000000..767d640015461 --- /dev/null +++ b/tests/cases/compiler/functionsWithImplicitReturnTypeAssignableToUndefined.ts @@ -0,0 +1,48 @@ +// @noImplicitReturns: false +// @strictNullChecks: true, false + +function f1(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is always assignable to unknown. +} + +type MyUnknown = unknown; +function f2(): unknown { + if (Math.random() < 0.5) return true; + + // Implicit return, but undefined is always assignable to unknown. +} + +function f3(): any { + // Implicit return, but undefined is always assignable to any. +} + +function f4(): void { + // Implicit return, but undefined is always assignable to void. +} + +function f5(): {} { + if (Math.random() < 0.5) return {}; + + // Implicit return, but undefined is assignable to object when strictNullChecks is off. +} + +function f6(): Record { + if (Math.random() < 0.5) return { "foo": true }; + + // Implicit return, but undefined is assignable to records (which are just fancy objects) + // when strictNullChecks is off. +} + +function f7(): null { + if (Math.random() < 0.5) return null; + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} + +function f8(): string | null { + if (Math.random() < 0.5) return "foo"; + + // Implicit return, but undefined is assignable to null when strictNullChecks is off. +} \ No newline at end of file