Pablo LION
Pablo LION

Reputation: 1435

Typing property of a variable which possibly has empty-object type

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.

Upvotes: 1

Views: 1485

Answers (2)

daylily
daylily

Reputation: 916

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.

Upvotes: 2

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

Upvotes: 1

Related Questions