1

Background

I'm using React and TypeScript and trying to add an optional parameter to a component. Then I run into a typescript error (ts:2339).

It seems that, when no props is passed, React will pass props={} instead of props=null or props=undefined. So the functional component will receive {}(an empty object), and I cannot change that.

Problem

How should I let TypeScript read the real optional parameters with pre-defined values?

const f = (param: {} | { k: string } = { k: 'v' }) => {
    var o
    // test 1 TS error: Property 'k' does not exist on type '{} | { k: string; }'.  Property 'k' does not exist on type '{}'.(2339)
    // o = (param)?.k 

    // test 2, nullity test. Same error as test1
    // if (Object.entries(param).length === 0) param = { k: 'v' };
    // o = (param)?.k

    // test 3, trying to avoid optional param assignment. Same error as test1
    // const _param = param ?? { k: 'v' }
    // o = _param.k

    // current work-around
    o = (param as any)?.k
    console.log(o)
}
f()

See the code in TS playground: https://www.typescriptlang.org/play?ssl=18&ssc=4&pln=1&pc=1#code/MYewdgzgLgBAZjAvDAFABwIYCcMFsBcMA3gL4wA+xMA1odFgJZgDmMZyRNhA5AG7dsAlEgB8xAFAwpMXthghJ0gPRKYUAKbQYARhgAVAMox1WLCCyEACmbQmoATxjdqAgCYhNMMCFjqAHgxa4Gr2tk6kFFS0MPRMzADcbNwAdFLWILZYDk4uMO6e3r4BQWAhYdykKSgATADMtQCcgopSKvJIqJg4uIIA-MnUMOItMG0aWtUANF4ArgA2cwzZ41CpBnjqxqbmMBgQappQ2iNtDAgoAPIARgBW6sCr6mBQjJro2HiCyXNPzFAAFkhEMgAAzCLp4DqcaJ8AQkeInVQgDrvbp9AbDaSjVQrGC1aYvexxNTIjC8EAMVzyNBQBjgDBzGAQ3C7CAQBjMMC4J6rGDrblbMxYVkHaDHLFtUCQWAAfWZHXlvV6UR4-DYiPayDlH1wGI1wBmph5MAA7uZqABabAgGZgVwjZHIVGQva7MD2dHUEZSiAgH7fEDMFAgZokcRwFCCIA

The param variable is never empty in this example and always has the property k. Yet I cannot use param?.k or anything I can come up with. I know that the any type works like disabling the TypeScript function. So, is there a way to let TypeScript read the true value of the parameter? Thanks.

What I did

I've read almost all similar questions on Stack Overflow but I see no good answer. Here are some references.

Pablo LION
  • 1,294
  • 6
  • 20
  • how is this component used in your template? I am not sure what you mean by: "It seems that react will pass props={} instead of props=null or props=undefined. So I the functional component need will receive {}(an empty object)" – Jensen Jul 14 '21 at 08:41
  • I did not make it clear. I meant in the case of "when no props were passed". I edited the question as per your suggestion. Thanks. – Pablo LION Jul 14 '21 at 09:22

2 Answers2

2

You can directy destructure the parameter in the function signature with a default value to always get the value:

const f = ({ k = 'v' }: { k?: string }) => {
  ...

and then do var o = k.

Alternatively you can test if k is a key of param. This can be done with:

if ('k' in param) {
  o = param.k
}

but it is more cumbersome.

daylily
  • 876
  • 5
  • 11
  • Thank you, @daylily. The first code style is not resolving the problem I described, which is to pass the parameter type correctly. Also, we need to check each property manually. The second code is exactly what I wanted. I suggest moving it as the principal solution. – Pablo LION Jul 14 '21 at 09:19
1
import { FC } from 'react'

type Props = {
    k: string
}

const foo: FC<Props> = (props = { k: 'v' }) => {

    const { k } = props // string

    return null as any

}

Since you have provided default value for props, you can omit any checkings of k