mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-14 07:02:44 -05:00
validate optional param/property
This commit is contained in:
@@ -45962,7 +45962,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
const container = isJSDocTemplateTag(declaration.parent) ? getJSDocHost(declaration.parent) : declaration.parent;
|
||||
if (!isFunctionLike(container)) continue;
|
||||
let paramReference: ParameterDeclaration | undefined;
|
||||
let referencePath: Name[] | undefined;
|
||||
let referencePath: Member[] | undefined;
|
||||
let hasInvalidReference = false;
|
||||
for (const paramDecl of container.parameters) {
|
||||
const typeNode = getEffectiveTypeAnnotationNode(paramDecl);
|
||||
@@ -45981,7 +45981,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
paramReference = paramDecl;
|
||||
}
|
||||
}
|
||||
if (!hasInvalidReference && referencePath) {
|
||||
if (!hasInvalidReference && referencePath && validateOptionality(paramReference!, constraint, referencePath)) {
|
||||
const symbolAndReference = constructNarrowableReference(paramReference!, referencePath);
|
||||
if (symbolAndReference) {
|
||||
if (symbolAndReference[0] && symbolAndReference[0] !== unknownSymbol) {
|
||||
@@ -45993,15 +45993,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
|
||||
return narrowableParams;
|
||||
// // For a parameter of declared type `T` to be a valid reference for narrowing, it must satisfy:
|
||||
// // - the parameter name is an identifier
|
||||
// // - if the parameter is optional, then `T`'s constraint must allow for undefined
|
||||
// function getValidParameterReference(paramDecl: ParameterDeclaration, constraint: Type): Identifier | undefined {
|
||||
// if (!isIdentifier(paramDecl.name)) return;
|
||||
// const isOptional = !!paramDecl.questionToken || isJSDocOptionalParameter(paramDecl);
|
||||
// if (isOptional && !containsUndefinedType(constraint)) return;
|
||||
// return paramDecl.name;
|
||||
// }
|
||||
|
||||
function isReferenceToTypeParameter(typeParam: TypeParameter, node: TypeReferenceNode) {
|
||||
return getTypeFromTypeReference(node) === typeParam;
|
||||
@@ -46030,7 +46021,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// an array of names that corresponds to the valid reference to `T`, if exactly one valid reference was found.
|
||||
// `path` is initially is empty; it's an accumulator for the path through valid property accesses.
|
||||
type Name = Identifier | StringLiteral;
|
||||
function getValidTypeParameterReference(typeNode: Node, typeParam: TypeParameter, path: Name[]): Name[] | boolean {
|
||||
type Member = PropertySignature & { name: Name };
|
||||
function getValidTypeParameterReference(typeNode: Node, typeParam: TypeParameter, path: Member[]): Member[] | boolean {
|
||||
switch (typeNode.kind) {
|
||||
case SyntaxKind.TypeReference:
|
||||
const type = getTypeFromTypeReference((typeNode as TypeReferenceNode));
|
||||
@@ -46077,7 +46069,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
case SyntaxKind.TypeLiteral:
|
||||
return getValidTypeParameterReferenceFromTypeElements((typeNode as TypeLiteralNode).members, typeParam, path);
|
||||
case SyntaxKind.IntersectionType:
|
||||
let validPath: Name[] | undefined;
|
||||
let validPath: Member[] | undefined;
|
||||
for (const type of (typeNode as IntersectionTypeNode).types) {
|
||||
const result = getValidTypeParameterReference(type, typeParam, path);
|
||||
if (!result) {
|
||||
@@ -46097,8 +46089,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
}
|
||||
}
|
||||
|
||||
function getValidTypeParameterReferenceFromTypeElements(members: NodeArray<TypeElement>, typeParam: TypeParameter, path: Name[]): Name[] | boolean {
|
||||
let validPath: Name[] | undefined;
|
||||
function getValidTypeParameterReferenceFromTypeElements(members: NodeArray<TypeElement>, typeParam: TypeParameter, path: Member[]): Member[] | boolean {
|
||||
let validPath: Member[] | undefined;
|
||||
for (const member of members) {
|
||||
if (!isTypeParameterReferenced(typeParam, member)) {
|
||||
continue;
|
||||
@@ -46106,13 +46098,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
if (!isPropertySignature(member)) {
|
||||
return false; // Unsupported reference to `T`, e.g. `[s: string]: T`.
|
||||
}
|
||||
if (!isIdentifier(member.name) && !isStringLiteral(member.name)) { // >> TODO: support others e.g. computed property?
|
||||
if (!isIdentifier(member.name) && !isStringLiteral(member.name)) {
|
||||
return false; // Unsupported property name, e.g. `[c]: T`
|
||||
}
|
||||
if (member.questionToken) {
|
||||
// >> TODO: account for property optionality
|
||||
}
|
||||
const result = getValidTypeParameterReference(member.type!, typeParam, [...path, member.name])
|
||||
const result = getValidTypeParameterReference(member.type!, typeParam, [...path, member as Member])
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
@@ -46126,6 +46115,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return validPath ?? true;
|
||||
}
|
||||
|
||||
function validateOptionality(paramDecl: ParameterDeclaration, constraint: Type, path: Member[]): boolean {
|
||||
// `function f<T extends ...>(obj: { prop?: { prop2: T }})` is not allowed.
|
||||
for (let i = 0; i < path.length - 1; i++) {
|
||||
if (path[i].questionToken) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const paramIsOptional = !!paramDecl.questionToken || isJSDocOptionalParameter(paramDecl);
|
||||
// `function f<T extends ...>(obj?: { prop: T })` is not allowed.
|
||||
if (paramIsOptional && path.length > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const isOptional = paramIsOptional || path.length > 0 && path[path.length - 1].questionToken;
|
||||
// `function f<T extends boolean>(obj?: T)` is not allowed under `strictNullChecks`.
|
||||
if (isOptional && strictNullChecks && !containsUndefinedType(constraint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Given a parameter declaration, and a name path to a reference of type parameter `T` in the type of the parameter,
|
||||
// construct a reference to the parameter property that corresponds to the `T` reference in the types.
|
||||
// Examples:
|
||||
@@ -46135,7 +46146,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
// `constructNarrowableReference(`{ b }: { b: T }`, [`b`])` ==> `b`
|
||||
// `constructNarrowableReference(`{ a }: { a: { b: T } }`, [`a`, `b`])` ==> `a.b`
|
||||
// `constructNarrowableReference(`{ a: { b }} : { a: { b: T }} }`, [`a`, `b`])` ==> `b`
|
||||
function constructNarrowableReference(paramDecl: ParameterDeclaration, path: Name[]): [Symbol, NarrowableReference] | undefined {
|
||||
function constructNarrowableReference(paramDecl: ParameterDeclaration, path: Member[]): [Symbol, NarrowableReference] | undefined {
|
||||
let currentName = paramDecl.name;
|
||||
let i = 0;
|
||||
for (; i < path.length; i++) {
|
||||
@@ -46143,7 +46154,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
break;
|
||||
}
|
||||
else if (isObjectBindingPattern(currentName)) {
|
||||
const name = path[i];
|
||||
const name = path[i].name;
|
||||
let nameText: __String | undefined;
|
||||
if (isIdentifier(name)) nameText = name.escapedText
|
||||
else {
|
||||
@@ -46172,7 +46183,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
let result: NarrowableReference = factory.cloneNode(currentName);
|
||||
const initialSymbol = getSymbolOfDeclaration(currentName.parent as ParameterDeclaration | BindingElement);
|
||||
for (let j = i; j < path.length; j++) {
|
||||
result = addName(result, path[j]);
|
||||
result = addName(result, path[j].name);
|
||||
}
|
||||
return [initialSymbol, result];
|
||||
}
|
||||
|
||||
@@ -19,9 +19,22 @@ dependentReturnType11.ts(152,25): error TS2322: Type '1' is not assignable to ty
|
||||
dependentReturnType11.ts(152,29): error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(205,13): error TS2322: Type '1' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(207,9): error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
dependentReturnType11.ts(221,9): error TS2322: Type '3' is not assignable to type 'RetU<T>'.
|
||||
dependentReturnType11.ts(224,9): error TS2322: Type '1' is not assignable to type 'RetU<T>'.
|
||||
dependentReturnType11.ts(226,5): error TS2322: Type '2' is not assignable to type 'RetU<T>'.
|
||||
dependentReturnType11.ts(260,9): error TS18048: 'param' is possibly 'undefined'.
|
||||
dependentReturnType11.ts(261,9): error TS2322: Type '3' is not assignable to type 'RetU<T>'.
|
||||
dependentReturnType11.ts(263,9): error TS18048: 'param' is possibly 'undefined'.
|
||||
dependentReturnType11.ts(264,9): error TS2322: Type '1' is not assignable to type 'RetU<T>'.
|
||||
dependentReturnType11.ts(266,5): error TS2322: Type '2' is not assignable to type 'RetU<T>'.
|
||||
dependentReturnType11.ts(270,9): error TS18048: 'param.prop1' is possibly 'undefined'.
|
||||
dependentReturnType11.ts(271,9): error TS2322: Type '3' is not assignable to type 'RetU<T>'.
|
||||
dependentReturnType11.ts(273,9): error TS18048: 'param.prop1' is possibly 'undefined'.
|
||||
dependentReturnType11.ts(274,9): error TS2322: Type '1' is not assignable to type 'RetU<T>'.
|
||||
dependentReturnType11.ts(276,5): error TS2322: Type '2' is not assignable to type 'RetU<T>'.
|
||||
|
||||
|
||||
==== dependentReturnType11.ts (21 errors) ====
|
||||
==== dependentReturnType11.ts (34 errors) ====
|
||||
type Ret<T extends boolean> =
|
||||
T extends true ? 1 :
|
||||
T extends false ? 2 :
|
||||
@@ -272,4 +285,98 @@ dependentReturnType11.ts(207,9): error TS2322: Type '2' is not assignable to typ
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '2' is not assignable to type 'Ret<T>'.
|
||||
}
|
||||
}
|
||||
|
||||
// Tests for optionality of parameters and properties.
|
||||
|
||||
type RetU<T> =
|
||||
T extends true ? 1 :
|
||||
T extends false ? 2 :
|
||||
T extends undefined ? 3 :
|
||||
never;
|
||||
|
||||
function fn1<T extends boolean>(param?: T): RetU<T> { // Bad.
|
||||
if (param == undefined) {
|
||||
return 3;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '3' is not assignable to type 'RetU<T>'.
|
||||
}
|
||||
if (param) {
|
||||
return 1;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '1' is not assignable to type 'RetU<T>'.
|
||||
}
|
||||
return 2;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '2' is not assignable to type 'RetU<T>'.
|
||||
}
|
||||
|
||||
function fn2<T extends boolean | undefined>(param?: T): RetU<T> {
|
||||
if (param == undefined) {
|
||||
return 3;
|
||||
}
|
||||
if (param) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn3<T extends boolean | undefined>(param: { prop?: T }): RetU<T> {
|
||||
if (param.prop == undefined) {
|
||||
return 3;
|
||||
}
|
||||
if (param.prop) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn4<T extends boolean | undefined>({ prop }: { prop?: T }): RetU<T> {
|
||||
if (prop == undefined) {
|
||||
return 3;
|
||||
}
|
||||
if (prop) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn5<T extends boolean | undefined>(param?: { prop: T }): RetU<T> { // Bad.
|
||||
if (param.prop == undefined) {
|
||||
~~~~~
|
||||
!!! error TS18048: 'param' is possibly 'undefined'.
|
||||
return 3;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '3' is not assignable to type 'RetU<T>'.
|
||||
}
|
||||
if (param.prop) {
|
||||
~~~~~
|
||||
!!! error TS18048: 'param' is possibly 'undefined'.
|
||||
return 1;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '1' is not assignable to type 'RetU<T>'.
|
||||
}
|
||||
return 2;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '2' is not assignable to type 'RetU<T>'.
|
||||
}
|
||||
|
||||
function fn6<T extends boolean | undefined>(param: { prop1?: { prop?: T } }): RetU<T> { // Bad.
|
||||
if (param.prop1.prop == undefined) {
|
||||
~~~~~~~~~~~
|
||||
!!! error TS18048: 'param.prop1' is possibly 'undefined'.
|
||||
return 3;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '3' is not assignable to type 'RetU<T>'.
|
||||
}
|
||||
if (param.prop1.prop) {
|
||||
~~~~~~~~~~~
|
||||
!!! error TS18048: 'param.prop1' is possibly 'undefined'.
|
||||
return 1;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '1' is not assignable to type 'RetU<T>'.
|
||||
}
|
||||
return 2;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '2' is not assignable to type 'RetU<T>'.
|
||||
}
|
||||
@@ -625,3 +625,173 @@ function h5<T extends boolean>(param: T): Ret<T> {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Tests for optionality of parameters and properties.
|
||||
|
||||
type RetU<T> =
|
||||
>RetU : Symbol(RetU, Decl(dependentReturnType11.ts, 208, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 212, 10))
|
||||
|
||||
T extends true ? 1 :
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 212, 10))
|
||||
|
||||
T extends false ? 2 :
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 212, 10))
|
||||
|
||||
T extends undefined ? 3 :
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 212, 10))
|
||||
|
||||
never;
|
||||
|
||||
function fn1<T extends boolean>(param?: T): RetU<T> { // Bad.
|
||||
>fn1 : Symbol(fn1, Decl(dependentReturnType11.ts, 216, 10))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 218, 13))
|
||||
>param : Symbol(param, Decl(dependentReturnType11.ts, 218, 32))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 218, 13))
|
||||
>RetU : Symbol(RetU, Decl(dependentReturnType11.ts, 208, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 218, 13))
|
||||
|
||||
if (param == undefined) {
|
||||
>param : Symbol(param, Decl(dependentReturnType11.ts, 218, 32))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
return 3;
|
||||
}
|
||||
if (param) {
|
||||
>param : Symbol(param, Decl(dependentReturnType11.ts, 218, 32))
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn2<T extends boolean | undefined>(param?: T): RetU<T> {
|
||||
>fn2 : Symbol(fn2, Decl(dependentReturnType11.ts, 226, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 228, 13))
|
||||
>param : Symbol(param, Decl(dependentReturnType11.ts, 228, 44))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 228, 13))
|
||||
>RetU : Symbol(RetU, Decl(dependentReturnType11.ts, 208, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 228, 13))
|
||||
|
||||
if (param == undefined) {
|
||||
>param : Symbol(param, Decl(dependentReturnType11.ts, 228, 44))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
return 3;
|
||||
}
|
||||
if (param) {
|
||||
>param : Symbol(param, Decl(dependentReturnType11.ts, 228, 44))
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn3<T extends boolean | undefined>(param: { prop?: T }): RetU<T> {
|
||||
>fn3 : Symbol(fn3, Decl(dependentReturnType11.ts, 236, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 238, 13))
|
||||
>param : Symbol(param, Decl(dependentReturnType11.ts, 238, 44))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType11.ts, 238, 52))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 238, 13))
|
||||
>RetU : Symbol(RetU, Decl(dependentReturnType11.ts, 208, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 238, 13))
|
||||
|
||||
if (param.prop == undefined) {
|
||||
>param.prop : Symbol(prop, Decl(dependentReturnType11.ts, 238, 52))
|
||||
>param : Symbol(param, Decl(dependentReturnType11.ts, 238, 44))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType11.ts, 238, 52))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
return 3;
|
||||
}
|
||||
if (param.prop) {
|
||||
>param.prop : Symbol(prop, Decl(dependentReturnType11.ts, 238, 52))
|
||||
>param : Symbol(param, Decl(dependentReturnType11.ts, 238, 44))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType11.ts, 238, 52))
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn4<T extends boolean | undefined>({ prop }: { prop?: T }): RetU<T> {
|
||||
>fn4 : Symbol(fn4, Decl(dependentReturnType11.ts, 246, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 248, 13))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType11.ts, 248, 45))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType11.ts, 248, 55))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 248, 13))
|
||||
>RetU : Symbol(RetU, Decl(dependentReturnType11.ts, 208, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 248, 13))
|
||||
|
||||
if (prop == undefined) {
|
||||
>prop : Symbol(prop, Decl(dependentReturnType11.ts, 248, 45))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
return 3;
|
||||
}
|
||||
if (prop) {
|
||||
>prop : Symbol(prop, Decl(dependentReturnType11.ts, 248, 45))
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn5<T extends boolean | undefined>(param?: { prop: T }): RetU<T> { // Bad.
|
||||
>fn5 : Symbol(fn5, Decl(dependentReturnType11.ts, 256, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 258, 13))
|
||||
>param : Symbol(param, Decl(dependentReturnType11.ts, 258, 44))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType11.ts, 258, 53))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 258, 13))
|
||||
>RetU : Symbol(RetU, Decl(dependentReturnType11.ts, 208, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 258, 13))
|
||||
|
||||
if (param.prop == undefined) {
|
||||
>param.prop : Symbol(prop, Decl(dependentReturnType11.ts, 258, 53))
|
||||
>param : Symbol(param, Decl(dependentReturnType11.ts, 258, 44))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType11.ts, 258, 53))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
return 3;
|
||||
}
|
||||
if (param.prop) {
|
||||
>param.prop : Symbol(prop, Decl(dependentReturnType11.ts, 258, 53))
|
||||
>param : Symbol(param, Decl(dependentReturnType11.ts, 258, 44))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType11.ts, 258, 53))
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn6<T extends boolean | undefined>(param: { prop1?: { prop?: T } }): RetU<T> { // Bad.
|
||||
>fn6 : Symbol(fn6, Decl(dependentReturnType11.ts, 266, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 268, 13))
|
||||
>param : Symbol(param, Decl(dependentReturnType11.ts, 268, 44))
|
||||
>prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 268, 52))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType11.ts, 268, 62))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 268, 13))
|
||||
>RetU : Symbol(RetU, Decl(dependentReturnType11.ts, 208, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType11.ts, 268, 13))
|
||||
|
||||
if (param.prop1.prop == undefined) {
|
||||
>param.prop1.prop : Symbol(prop, Decl(dependentReturnType11.ts, 268, 62))
|
||||
>param.prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 268, 52))
|
||||
>param : Symbol(param, Decl(dependentReturnType11.ts, 268, 44))
|
||||
>prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 268, 52))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType11.ts, 268, 62))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
return 3;
|
||||
}
|
||||
if (param.prop1.prop) {
|
||||
>param.prop1.prop : Symbol(prop, Decl(dependentReturnType11.ts, 268, 62))
|
||||
>param.prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 268, 52))
|
||||
>param : Symbol(param, Decl(dependentReturnType11.ts, 268, 44))
|
||||
>prop1 : Symbol(prop1, Decl(dependentReturnType11.ts, 268, 52))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType11.ts, 268, 62))
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -829,3 +829,248 @@ function h5<T extends boolean>(param: T): Ret<T> {
|
||||
> : ^
|
||||
}
|
||||
}
|
||||
|
||||
// Tests for optionality of parameters and properties.
|
||||
|
||||
type RetU<T> =
|
||||
>RetU : RetU<T>
|
||||
> : ^^^^^^^
|
||||
|
||||
T extends true ? 1 :
|
||||
>true : true
|
||||
> : ^^^^
|
||||
|
||||
T extends false ? 2 :
|
||||
>false : false
|
||||
> : ^^^^^
|
||||
|
||||
T extends undefined ? 3 :
|
||||
never;
|
||||
|
||||
function fn1<T extends boolean>(param?: T): RetU<T> { // Bad.
|
||||
>fn1 : <T extends boolean>(param?: T) => RetU<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^^ ^^^^^
|
||||
>param : T | undefined
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
if (param == undefined) {
|
||||
>param == undefined : boolean
|
||||
> : ^^^^^^^
|
||||
>param : T | undefined
|
||||
> : ^^^^^^^^^^^^^
|
||||
>undefined : undefined
|
||||
> : ^^^^^^^^^
|
||||
|
||||
return 3;
|
||||
>3 : 3
|
||||
> : ^
|
||||
}
|
||||
if (param) {
|
||||
>param : T
|
||||
> : ^
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
> : ^
|
||||
}
|
||||
return 2;
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function fn2<T extends boolean | undefined>(param?: T): RetU<T> {
|
||||
>fn2 : <T extends boolean | undefined>(param?: T) => RetU<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^^ ^^^^^
|
||||
>param : T | undefined
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
if (param == undefined) {
|
||||
>param == undefined : boolean
|
||||
> : ^^^^^^^
|
||||
>param : T | undefined
|
||||
> : ^^^^^^^^^^^^^
|
||||
>undefined : undefined
|
||||
> : ^^^^^^^^^
|
||||
|
||||
return 3;
|
||||
>3 : 3
|
||||
> : ^
|
||||
}
|
||||
if (param) {
|
||||
>param : NonNullable<T>
|
||||
> : ^^^^^^^^^^^^^^
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
> : ^
|
||||
}
|
||||
return 2;
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function fn3<T extends boolean | undefined>(param: { prop?: T }): RetU<T> {
|
||||
>fn3 : <T extends boolean | undefined>(param: { prop?: T; }) => RetU<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : { prop?: T; }
|
||||
> : ^^^^^^^^^ ^^^
|
||||
>prop : T | undefined
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
if (param.prop == undefined) {
|
||||
>param.prop == undefined : boolean
|
||||
> : ^^^^^^^
|
||||
>param.prop : T | undefined
|
||||
> : ^^^^^^^^^^^^^
|
||||
>param : { prop?: T; }
|
||||
> : ^^^^^^^^^ ^^^
|
||||
>prop : T | undefined
|
||||
> : ^^^^^^^^^^^^^
|
||||
>undefined : undefined
|
||||
> : ^^^^^^^^^
|
||||
|
||||
return 3;
|
||||
>3 : 3
|
||||
> : ^
|
||||
}
|
||||
if (param.prop) {
|
||||
>param.prop : NonNullable<T>
|
||||
> : ^^^^^^^^^^^^^^
|
||||
>param : { prop?: T; }
|
||||
> : ^^^^^^^^^ ^^^
|
||||
>prop : NonNullable<T>
|
||||
> : ^^^^^^^^^^^^^^
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
> : ^
|
||||
}
|
||||
return 2;
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function fn4<T extends boolean | undefined>({ prop }: { prop?: T }): RetU<T> {
|
||||
>fn4 : <T extends boolean | undefined>({ prop }: { prop?: T; }) => RetU<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>prop : T | undefined
|
||||
> : ^^^^^^^^^^^^^
|
||||
>prop : T | undefined
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
if (prop == undefined) {
|
||||
>prop == undefined : boolean
|
||||
> : ^^^^^^^
|
||||
>prop : T | undefined
|
||||
> : ^^^^^^^^^^^^^
|
||||
>undefined : undefined
|
||||
> : ^^^^^^^^^
|
||||
|
||||
return 3;
|
||||
>3 : 3
|
||||
> : ^
|
||||
}
|
||||
if (prop) {
|
||||
>prop : NonNullable<T>
|
||||
> : ^^^^^^^^^^^^^^
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
> : ^
|
||||
}
|
||||
return 2;
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function fn5<T extends boolean | undefined>(param?: { prop: T }): RetU<T> { // Bad.
|
||||
>fn5 : <T extends boolean | undefined>(param?: { prop: T; }) => RetU<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^^ ^^^^^
|
||||
>param : { prop: T; } | undefined
|
||||
> : ^^^^^^^^ ^^^^^^^^^^^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
|
||||
if (param.prop == undefined) {
|
||||
>param.prop == undefined : boolean
|
||||
> : ^^^^^^^
|
||||
>param.prop : T
|
||||
> : ^
|
||||
>param : { prop: T; } | undefined
|
||||
> : ^^^^^^^^ ^^^^^^^^^^^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>undefined : undefined
|
||||
> : ^^^^^^^^^
|
||||
|
||||
return 3;
|
||||
>3 : 3
|
||||
> : ^
|
||||
}
|
||||
if (param.prop) {
|
||||
>param.prop : NonNullable<T>
|
||||
> : ^^^^^^^^^^^^^^
|
||||
>param : { prop: T; } | undefined
|
||||
> : ^^^^^^^^ ^^^^^^^^^^^^^^^
|
||||
>prop : NonNullable<T>
|
||||
> : ^^^^^^^^^^^^^^
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
> : ^
|
||||
}
|
||||
return 2;
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function fn6<T extends boolean | undefined>(param: { prop1?: { prop?: T } }): RetU<T> { // Bad.
|
||||
>fn6 : <T extends boolean | undefined>(param: { prop1?: { prop?: T; }; }) => RetU<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : { prop1?: { prop?: T; }; }
|
||||
> : ^^^^^^^^^^ ^^^
|
||||
>prop1 : { prop?: T; } | undefined
|
||||
> : ^^^^^^^^^ ^^^^^^^^^^^^^^^
|
||||
>prop : T | undefined
|
||||
> : ^^^^^^^^^^^^^
|
||||
|
||||
if (param.prop1.prop == undefined) {
|
||||
>param.prop1.prop == undefined : boolean
|
||||
> : ^^^^^^^
|
||||
>param.prop1.prop : T | undefined
|
||||
> : ^^^^^^^^^^^^^
|
||||
>param.prop1 : { prop?: T; } | undefined
|
||||
> : ^^^^^^^^^ ^^^^^^^^^^^^^^^
|
||||
>param : { prop1?: { prop?: T; }; }
|
||||
> : ^^^^^^^^^^ ^^^
|
||||
>prop1 : { prop?: T; } | undefined
|
||||
> : ^^^^^^^^^ ^^^^^^^^^^^^^^^
|
||||
>prop : T | undefined
|
||||
> : ^^^^^^^^^^^^^
|
||||
>undefined : undefined
|
||||
> : ^^^^^^^^^
|
||||
|
||||
return 3;
|
||||
>3 : 3
|
||||
> : ^
|
||||
}
|
||||
if (param.prop1.prop) {
|
||||
>param.prop1.prop : NonNullable<T>
|
||||
> : ^^^^^^^^^^^^^^
|
||||
>param.prop1 : { prop?: T; } | undefined
|
||||
> : ^^^^^^^^^ ^^^^^^^^^^^^^^^
|
||||
>param : { prop1?: { prop?: T; }; }
|
||||
> : ^^^^^^^^^^ ^^^
|
||||
>prop1 : { prop?: T; } | undefined
|
||||
> : ^^^^^^^^^ ^^^^^^^^^^^^^^^
|
||||
>prop : NonNullable<T>
|
||||
> : ^^^^^^^^^^^^^^
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
> : ^
|
||||
}
|
||||
return 2;
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
56
tests/baselines/reference/dependentReturnType12.errors.txt
Normal file
56
tests/baselines/reference/dependentReturnType12.errors.txt
Normal file
@@ -0,0 +1,56 @@
|
||||
dependentReturnType12.ts(31,9): error TS2322: Type '1' is not assignable to type 'RetU<T>'.
|
||||
dependentReturnType12.ts(33,5): error TS2322: Type '2' is not assignable to type 'RetU<T>'.
|
||||
dependentReturnType12.ts(38,9): error TS2322: Type '1' is not assignable to type 'RetU<T>'.
|
||||
dependentReturnType12.ts(40,5): error TS2322: Type '2' is not assignable to type 'RetU<T>'.
|
||||
|
||||
|
||||
==== dependentReturnType12.ts (4 errors) ====
|
||||
// Tests for optionality of parameters and properties.
|
||||
|
||||
type RetU<T> =
|
||||
T extends string ? 2 :
|
||||
T extends number ? 1 :
|
||||
never;
|
||||
|
||||
function fn1<T extends string | number>(param?: T): RetU<T> {
|
||||
if (typeof param === "number") {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn3<T extends string | number>(param: { prop?: T }): RetU<T> {
|
||||
if (typeof param.prop === "number") {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn4<T extends string | number>({ prop }: { prop?: T }): RetU<T> {
|
||||
if (typeof prop === "number") {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn5<T extends string | number>(param?: { prop: T }): RetU<T> { // Bad.
|
||||
if (typeof param.prop === "number") {
|
||||
return 1;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '1' is not assignable to type 'RetU<T>'.
|
||||
}
|
||||
return 2;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '2' is not assignable to type 'RetU<T>'.
|
||||
}
|
||||
|
||||
function fn6<T extends string | number>(param: { prop1?: { prop?: T } }): RetU<T> { // Bad.
|
||||
if (typeof param.prop1.prop === "number") {
|
||||
return 1;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '1' is not assignable to type 'RetU<T>'.
|
||||
}
|
||||
return 2;
|
||||
~~~~~~
|
||||
!!! error TS2322: Type '2' is not assignable to type 'RetU<T>'.
|
||||
}
|
||||
109
tests/baselines/reference/dependentReturnType12.symbols
Normal file
109
tests/baselines/reference/dependentReturnType12.symbols
Normal file
@@ -0,0 +1,109 @@
|
||||
//// [tests/cases/compiler/dependentReturnType12.ts] ////
|
||||
|
||||
=== dependentReturnType12.ts ===
|
||||
// Tests for optionality of parameters and properties.
|
||||
|
||||
type RetU<T> =
|
||||
>RetU : Symbol(RetU, Decl(dependentReturnType12.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 2, 10))
|
||||
|
||||
T extends string ? 2 :
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 2, 10))
|
||||
|
||||
T extends number ? 1 :
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 2, 10))
|
||||
|
||||
never;
|
||||
|
||||
function fn1<T extends string | number>(param?: T): RetU<T> {
|
||||
>fn1 : Symbol(fn1, Decl(dependentReturnType12.ts, 5, 10))
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 7, 13))
|
||||
>param : Symbol(param, Decl(dependentReturnType12.ts, 7, 40))
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 7, 13))
|
||||
>RetU : Symbol(RetU, Decl(dependentReturnType12.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 7, 13))
|
||||
|
||||
if (typeof param === "number") {
|
||||
>param : Symbol(param, Decl(dependentReturnType12.ts, 7, 40))
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn3<T extends string | number>(param: { prop?: T }): RetU<T> {
|
||||
>fn3 : Symbol(fn3, Decl(dependentReturnType12.ts, 12, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 14, 13))
|
||||
>param : Symbol(param, Decl(dependentReturnType12.ts, 14, 40))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType12.ts, 14, 48))
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 14, 13))
|
||||
>RetU : Symbol(RetU, Decl(dependentReturnType12.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 14, 13))
|
||||
|
||||
if (typeof param.prop === "number") {
|
||||
>param.prop : Symbol(prop, Decl(dependentReturnType12.ts, 14, 48))
|
||||
>param : Symbol(param, Decl(dependentReturnType12.ts, 14, 40))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType12.ts, 14, 48))
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn4<T extends string | number>({ prop }: { prop?: T }): RetU<T> {
|
||||
>fn4 : Symbol(fn4, Decl(dependentReturnType12.ts, 19, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 21, 13))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType12.ts, 21, 41))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType12.ts, 21, 51))
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 21, 13))
|
||||
>RetU : Symbol(RetU, Decl(dependentReturnType12.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 21, 13))
|
||||
|
||||
if (typeof prop === "number") {
|
||||
>prop : Symbol(prop, Decl(dependentReturnType12.ts, 21, 41))
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn5<T extends string | number>(param?: { prop: T }): RetU<T> { // Bad.
|
||||
>fn5 : Symbol(fn5, Decl(dependentReturnType12.ts, 26, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 28, 13))
|
||||
>param : Symbol(param, Decl(dependentReturnType12.ts, 28, 40))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType12.ts, 28, 49))
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 28, 13))
|
||||
>RetU : Symbol(RetU, Decl(dependentReturnType12.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 28, 13))
|
||||
|
||||
if (typeof param.prop === "number") {
|
||||
>param.prop : Symbol(prop, Decl(dependentReturnType12.ts, 28, 49))
|
||||
>param : Symbol(param, Decl(dependentReturnType12.ts, 28, 40))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType12.ts, 28, 49))
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn6<T extends string | number>(param: { prop1?: { prop?: T } }): RetU<T> { // Bad.
|
||||
>fn6 : Symbol(fn6, Decl(dependentReturnType12.ts, 33, 1))
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 35, 13))
|
||||
>param : Symbol(param, Decl(dependentReturnType12.ts, 35, 40))
|
||||
>prop1 : Symbol(prop1, Decl(dependentReturnType12.ts, 35, 48))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType12.ts, 35, 58))
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 35, 13))
|
||||
>RetU : Symbol(RetU, Decl(dependentReturnType12.ts, 0, 0))
|
||||
>T : Symbol(T, Decl(dependentReturnType12.ts, 35, 13))
|
||||
|
||||
if (typeof param.prop1.prop === "number") {
|
||||
>param.prop1.prop : Symbol(prop, Decl(dependentReturnType12.ts, 35, 58))
|
||||
>param.prop1 : Symbol(prop1, Decl(dependentReturnType12.ts, 35, 48))
|
||||
>param : Symbol(param, Decl(dependentReturnType12.ts, 35, 40))
|
||||
>prop1 : Symbol(prop1, Decl(dependentReturnType12.ts, 35, 48))
|
||||
>prop : Symbol(prop, Decl(dependentReturnType12.ts, 35, 58))
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
163
tests/baselines/reference/dependentReturnType12.types
Normal file
163
tests/baselines/reference/dependentReturnType12.types
Normal file
@@ -0,0 +1,163 @@
|
||||
//// [tests/cases/compiler/dependentReturnType12.ts] ////
|
||||
|
||||
=== dependentReturnType12.ts ===
|
||||
// Tests for optionality of parameters and properties.
|
||||
|
||||
type RetU<T> =
|
||||
>RetU : RetU<T>
|
||||
> : ^^^^^^^
|
||||
|
||||
T extends string ? 2 :
|
||||
T extends number ? 1 :
|
||||
never;
|
||||
|
||||
function fn1<T extends string | number>(param?: T): RetU<T> {
|
||||
>fn1 : <T extends string | number>(param?: T) => RetU<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^^ ^^^^^
|
||||
>param : T
|
||||
> : ^
|
||||
|
||||
if (typeof param === "number") {
|
||||
>typeof param === "number" : boolean
|
||||
> : ^^^^^^^
|
||||
>typeof param : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>param : T
|
||||
> : ^
|
||||
>"number" : "number"
|
||||
> : ^^^^^^^^
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
> : ^
|
||||
}
|
||||
return 2;
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function fn3<T extends string | number>(param: { prop?: T }): RetU<T> {
|
||||
>fn3 : <T extends string | number>(param: { prop?: T; }) => RetU<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : { prop?: T; }
|
||||
> : ^^^^^^^^^ ^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
|
||||
if (typeof param.prop === "number") {
|
||||
>typeof param.prop === "number" : boolean
|
||||
> : ^^^^^^^
|
||||
>typeof param.prop : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>param.prop : T
|
||||
> : ^
|
||||
>param : { prop?: T; }
|
||||
> : ^^^^^^^^^ ^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>"number" : "number"
|
||||
> : ^^^^^^^^
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
> : ^
|
||||
}
|
||||
return 2;
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function fn4<T extends string | number>({ prop }: { prop?: T }): RetU<T> {
|
||||
>fn4 : <T extends string | number>({ prop }: { prop?: T; }) => RetU<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>prop : T
|
||||
> : ^
|
||||
|
||||
if (typeof prop === "number") {
|
||||
>typeof prop === "number" : boolean
|
||||
> : ^^^^^^^
|
||||
>typeof prop : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>"number" : "number"
|
||||
> : ^^^^^^^^
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
> : ^
|
||||
}
|
||||
return 2;
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function fn5<T extends string | number>(param?: { prop: T }): RetU<T> { // Bad.
|
||||
>fn5 : <T extends string | number>(param?: { prop: T; }) => RetU<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^^ ^^^^^
|
||||
>param : { prop: T; }
|
||||
> : ^^^^^^^^ ^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
|
||||
if (typeof param.prop === "number") {
|
||||
>typeof param.prop === "number" : boolean
|
||||
> : ^^^^^^^
|
||||
>typeof param.prop : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>param.prop : T
|
||||
> : ^
|
||||
>param : { prop: T; }
|
||||
> : ^^^^^^^^ ^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>"number" : "number"
|
||||
> : ^^^^^^^^
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
> : ^
|
||||
}
|
||||
return 2;
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
|
||||
function fn6<T extends string | number>(param: { prop1?: { prop?: T } }): RetU<T> { // Bad.
|
||||
>fn6 : <T extends string | number>(param: { prop1?: { prop?: T; }; }) => RetU<T>
|
||||
> : ^ ^^^^^^^^^ ^^ ^^ ^^^^^
|
||||
>param : { prop1?: { prop?: T; }; }
|
||||
> : ^^^^^^^^^^ ^^^
|
||||
>prop1 : { prop?: T; }
|
||||
> : ^^^^^^^^^ ^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
|
||||
if (typeof param.prop1.prop === "number") {
|
||||
>typeof param.prop1.prop === "number" : boolean
|
||||
> : ^^^^^^^
|
||||
>typeof param.prop1.prop : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
>param.prop1.prop : T
|
||||
> : ^
|
||||
>param.prop1 : { prop?: T; }
|
||||
> : ^^^^^^^^^ ^^^
|
||||
>param : { prop1?: { prop?: T; }; }
|
||||
> : ^^^^^^^^^^ ^^^
|
||||
>prop1 : { prop?: T; }
|
||||
> : ^^^^^^^^^ ^^^
|
||||
>prop : T
|
||||
> : ^
|
||||
>"number" : "number"
|
||||
> : ^^^^^^^^
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
> : ^
|
||||
}
|
||||
return 2;
|
||||
>2 : 2
|
||||
> : ^
|
||||
}
|
||||
@@ -209,4 +209,72 @@ function h5<T extends boolean>(param: T): Ret<T> {
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Tests for optionality of parameters and properties.
|
||||
|
||||
type RetU<T> =
|
||||
T extends true ? 1 :
|
||||
T extends false ? 2 :
|
||||
T extends undefined ? 3 :
|
||||
never;
|
||||
|
||||
function fn1<T extends boolean>(param?: T): RetU<T> { // Bad.
|
||||
if (param == undefined) {
|
||||
return 3;
|
||||
}
|
||||
if (param) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn2<T extends boolean | undefined>(param?: T): RetU<T> {
|
||||
if (param == undefined) {
|
||||
return 3;
|
||||
}
|
||||
if (param) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn3<T extends boolean | undefined>(param: { prop?: T }): RetU<T> {
|
||||
if (param.prop == undefined) {
|
||||
return 3;
|
||||
}
|
||||
if (param.prop) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn4<T extends boolean | undefined>({ prop }: { prop?: T }): RetU<T> {
|
||||
if (prop == undefined) {
|
||||
return 3;
|
||||
}
|
||||
if (prop) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn5<T extends boolean | undefined>(param?: { prop: T }): RetU<T> { // Bad.
|
||||
if (param.prop == undefined) {
|
||||
return 3;
|
||||
}
|
||||
if (param.prop) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn6<T extends boolean | undefined>(param: { prop1?: { prop?: T } }): RetU<T> { // Bad.
|
||||
if (param.prop1.prop == undefined) {
|
||||
return 3;
|
||||
}
|
||||
if (param.prop1.prop) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
45
tests/cases/compiler/dependentReturnType12.ts
Normal file
45
tests/cases/compiler/dependentReturnType12.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
// @noEmit: true
|
||||
// @strict: false
|
||||
|
||||
|
||||
// Tests for optionality of parameters and properties.
|
||||
|
||||
type RetU<T> =
|
||||
T extends string ? 2 :
|
||||
T extends number ? 1 :
|
||||
never;
|
||||
|
||||
function fn1<T extends string | number>(param?: T): RetU<T> {
|
||||
if (typeof param === "number") {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn3<T extends string | number>(param: { prop?: T }): RetU<T> {
|
||||
if (typeof param.prop === "number") {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn4<T extends string | number>({ prop }: { prop?: T }): RetU<T> {
|
||||
if (typeof prop === "number") {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn5<T extends string | number>(param?: { prop: T }): RetU<T> { // Bad.
|
||||
if (typeof param.prop === "number") {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
function fn6<T extends string | number>(param: { prop1?: { prop?: T } }): RetU<T> { // Bad.
|
||||
if (typeof param.prop1.prop === "number") {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
Reference in New Issue
Block a user