question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Treating `undefined` parameters as optional

See original GitHub issue

tsc: 2.2.0-dev.20161116

Discover this behavior from https://github.com/acdlite/flux-standard-action/pull/45/commits/78a9065914b2ca4848dfba8fc0b47c54e2d0e319

This is the original code:

export interface FSA<Payload, Meta> {
  ...
  payload?: Payload;
  ...
}

However, this does not work well with type guard:

function isSomeAction(action: any): action is FSA<{ message: string }, void> {
  return true;
}

let action = {...};
if (isSomeAction(action)) {
  // `action.payload` may be undefined.
  console.log(action.payload.message);
}

Since generic type can be anything, including undefined, I’m considering to remove the optional designation:

export interface FSA<Payload, Meta> {
  ...
  payload: Payload;
  ...
}

// now type guard works
let action = {...};
if (isSomeAction(action)) {
  console.log(action.payload.message);
}

However, now the creation code fail:

function createSomeAction(): FSA<undefined, undefined> {
  // error: `payload` and `meta` are required
  return { type: 'SOME_ACTION' };
}

The workaround is to depends on infer type:

function createSomeAction() {
  return { type: 'SOME_ACTION' };
}

or specify it:

function createSomeAction(): FSA<undefined, undefined> {
  return { 
    type: 'SOME_ACTION',
    payload: undefined,
    meta: undefined
  };
}

Is there a better solution? 🌷

Issue Analytics

  • State:open
  • Created 7 years ago
  • Reactions:71
  • Comments:38 (12 by maintainers)

github_iconTop GitHub Comments

37reactions
RyanCavanaughcommented, Nov 28, 2017

Approved. This will probably be a hairy change so we’ll take a first stab at it unless someone wants to jump in. We don’t think there will be breaking changes but we’ll need to investigate

25reactions
minajevscommented, Oct 15, 2018

For anyone still waiting for optional function arguments, it is now possible to simulate that using new tuple types and spread expressions:

type OptionalSpread<T = undefined> =
    T extends undefined
    ? []
    : [T]

const foo = <T = undefined>(...args: OptionalSpread<T>): void => {
    const arg = args[0] // Type of: T = undefined
}

// undefined inferred
foo()               // OK
foo(42)             // OK <----single argument type is inferred, can't do anything about it   

// undefined explicit
foo<undefined>()    // OK
foo<undefined>(42)  // ERROR Expected 0 arguments, but got 1.

// number
foo<number>(42)     // OK
foo<number>()       // ERROR Expected 1 arguments, but got 0.
foo<number>("bar")  // ERROR Argument is not assignable to parameter of type 'number'.

it has a limitation with inferred argument type though, which is solved by explicitly specifying undefined argument type

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to Deal with Optional Things and "Undefined" in TypeScript
Working with JavaScript means working with undefined . It's a standard way to say, “This thing you asked for doesn't exist.”.
Read more >
How to deal with TypeScript not treating uninitialized optional ...
What I expect from these function typings is to treat lack of value as undefined , but TypeScript doesn't allow this, and instead...
Read more >
When to use typescript optional "?" parameter vs explicit ...
Typescript “?” operator means that parameter is optional, it's not necessary to pass it in component/function. Undefined means that parameter ...
Read more >
TypeScript Optional Parameters
First, use the ? after the c parameter. · Second, check if the argument is passed to the function by using the expression...
Read more >
Nullable types and optional parameters/properties (TypeScript)
Note: an optional parameter is not completely the same as a parameter that needs to be provided but can be undefined! function test2(a:...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found