Skip to content

TypeScript doesn't respect declared function argument type definition #51487

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

Closed
jez9999 opened this issue Nov 11, 2022 · 7 comments
Closed

TypeScript doesn't respect declared function argument type definition #51487

jez9999 opened this issue Nov 11, 2022 · 7 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@jez9999
Copy link

jez9999 commented Nov 11, 2022

Bug Report

πŸ”Ž Search Terms

argument type inconsistent respect function definition

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about 4.8.4

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

class Foo {
    constructor() {
        this.bar = 123;
    }
    bar: number;
}

function isSpecified<T>(input: undefined | null | T): input is T {
    return ((typeof input !== "undefined") && (input !== null));
}

function variableAsArg(inputVar?: number) {
    const fooInstance = new Foo();

    if (isSpecified(inputVar)) {
        console.log(`Var is specified: ${inputVar}`);
        fooInstance.bar = inputVar;
    }
    else {
        console.log("var is unspecified")
    }
}

function variableAsConst() {
    const fooInstance = new Foo();

    const inputVar: null | undefined | number = undefined;
    if (isSpecified(inputVar)) {
        console.log(`Var is specified: ${inputVar}`);
        fooInstance.bar = inputVar; // <-- Error
    }
    else {
        console.log("var is unspecified")
    }
}

const inputVar: null | undefined | number = undefined;
//variableAsArg(inputVar);
variableAsConst();

πŸ™ Actual behavior

When a variable is declared in the same block and assigned undefined, even when its type is explicitly declared to have | number, its type is treated as null | undefined rather than number | null | undefined when passed to a function. I guess TS thinks it's being helpful here, but it seems to me like annoying inconsistent behaviour that breaks my type guard function when I've explicitly told TS that the variable type should be considered | number. Because of this behaviour, in that circumstance, my isSpecified function no longer acts as a type guard against null | undefined and I get an error from TS.

πŸ™‚ Expected behavior

TS should always respect the explicit type that the variable is declared to be whether it's a function argument or declared in the same code block as a const.

@MartinJohns
Copy link
Contributor

Assignment narrows the variable. This is working as intended. You can use the new satisfies operator instead.

@jez9999
Copy link
Author

jez9999 commented Nov 11, 2022

Could you give an example as to how satisfies fixes this problem?

@MartinJohns
Copy link
Contributor

Nevermind, I talked without verifying. satisfies does not help. But you can use a type assertion to prevent narrowing: const inputVar = undefined as null | undefined | number;

@jez9999
Copy link
Author

jez9999 commented Nov 11, 2022

Yep, that does fix it. I still find it kind of odd that assignment narrow the type of a variable whose type is explicitly declared, but oh well. I mean in C#, int? foo = 2 wouldn't turn the variable into an int under any circumstances.

@MartinJohns
Copy link
Contributor

C# doesn't have union types, so the argument is moot.

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Nov 11, 2022
@RyanCavanaugh
Copy link
Member

This used to not be the case, and people found that behavior very annoying and inconsistent, so we changed to this other behavior which is apparently also very annoying and inconsistent. Can't win 'em all πŸ˜…

@typescript-bot
Copy link
Collaborator

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants