Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Function fields in class with conditional optionality of parameters #57139

Copy link
Copy link
@BenjaBobs

Description

@BenjaBobs
Issue body actions

🔎 Search Terms

"class", "conditinal types", "conditional functions parameters", "optional function parameters"

🕗 Version & Regression Information

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

⏯ Playground Link

https://www.typescriptlang.org/play?ts=5.4.0-dev.20240123#code/MYGwhgzhAEAqCmEAuBhcUA8sCSA7ADgK5IB80A3gFDTQD0tcAnvvNAOQAUYATgOYQB+AFxw8RJAEpoAXjIA3APYBLACZtoSmLgVJokCEt64wAIxCskC6NToMkzVmxwFi0eAA8k8XCpiEf8ABmSrjwKtAC0Fx8giLO4tAAPtD+KkEhYVKy0Iqq0CLR-HFixFnyymo2gQoKxS66Hl4+fgHBoSo2NJGFsaL1ZTkVnflRPEV94gO54TbSozHCE6Ui0zJk5AC+lFuUwAq4yNAK+EhK+2AgMtChAO5wiKjoEBip6e0kHBIA3JTHp+cgAB01QUny+tmgAHkANIAGj0MA8LGAXg6u32h248AAjoQlFjwnNbvdkGh9BhcIQALYmeDcD7fShY3H4sLAmpgiEAUW43AU3HhY2p3l01W4ehi0BukGuOmg+D5clUYUFiPcyNRTJxeIJ7NBAEZvhCYaq3Or4CiwpRKPRoNhdGB8CweDBLFL+QBrI7EAxpI6BaCgfSB-ZeTyUewsKEnLBkOY9RawKYVH6R1gAJRxsauPTiydUP3RBwdIkhMcpNLpcfm-EWFdp3AGmx+e2L0BMIkz2Ip1Ib1YTInrdKbG0LaegKAAFhaPdm5rAzU1fClWhlwpEy0hs52s7ASC2MbpgCIpzOXqv3jmxr0h421hRR0XDioT9PgLPb-3r3Xe8P783rVtABNBRCEDMBcClbhHQRPRcEYI5IKQacNFwJRTguHILkIeBdieElHn0AAmLASlICgbBMHhXzPeJiC-BY6kmf8thoKiAC8aPfUj6n7AclkkFipBlCDGG2a1W0OP4zmMEAiKuYkEFJJ4SNeNowgZH5pIBIjASo7hOVtE1YKRC1NW02TdI4wyGGMmVTMtNFJN0ZkdTCeSiXgO4lMIqASM-MEtRZAkrJ4GzoB5PkBQlXhhVwUV+RimBpS0OUFQUJU0hUU0HM1VzWRUUL2PCyL+UFPg4oS8VrylGVtF0dLMpVEzzUcoK3MKvSwsNcEjLhFqNStfKQq64qeuNfr7NazUgA

💻 Code

class TestClass<TInput> {
  // Type '(args?: TInput) => void' is not assignable to 
  // type 'TInput extends undefined ? (args?: TInput | undefined) => void : (args: TInput) => void'
  foo: TInput extends undefined
    ? (args?: TInput) => void
    : (args: TInput) => void 
  = (args?: TInput): void => {}
}

const optional = new TestClass<undefined>();
optional.foo(); // OK, as expected

const required = new TestClass<number>();
required.foo(); // Error, argument for args was not provided, as expected
required.foo(1); // OK, as expected

// It appears to work outside of class context
type Opt<T> = (args?: T) => void;
type Req<T> = (args: T) => void;

const a: Opt<number> = (args?: number) => {};
const b: Req<number> = (args?: number) => {};

type Check<T> = T extends undefined ? Opt<T> : Req<T>;
const c: Check<undefined> = (args?: number) => {};
const d: Check<number> = (args?: number) => {};

// You can wrap as any on the initial value
class TestClass2<TInput> {
  // Type '(args?: TInput) => void' is not assignable to type 'Check<TInput>'.
  bar: Check<TInput> = (args?: TInput) => {}
  baz: Check<TInput> = ((args?: TInput) => {}) as any
}

const optional2 = new TestClass2<undefined>();
optional2.bar(); // OK, as expected
optional2.baz(); // OK, as expected

const required2 = new TestClass2<number>();
required2.bar(); // Error, argument for args was not provided, as expected
required2.baz(); // Error, argument for args was not provided, as expected
required2.bar(1); // OK, as expected
required2.baz(1); // OK, as expected

🙁 Actual behavior

class TestClass<TInput> {
  // Type '(args?: TInput) => void' is not assignable to 
  // type 'TInput extends undefined ? (args?: TInput | undefined) => void : (args: TInput) => void'
  foo: TInput extends undefined
    ? (args?: TInput) => void
    : (args: TInput) => void 
  = (args?: TInput): void => {}
}

🙂 Expected behavior

class TestClass<TInput> {
  // This should be possible
  foo: TInput extends undefined
    ? (args?: TInput) => void
    : (args: TInput) => void 
  = (args?: TInput): void => {}
}

I would expect this to work because it works outside of class definitions, and because having the implementation function args be optional should be able to handle both cases.

Additional information about the issue

Might be related to #12400

Reactions are currently unavailable

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already createdAn existing issue was already created

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.