0

My problem: When i set one of three optional values, then that only value is visible, other default values are gone.

type ComponentProps = {
 title: string,
 children: JSX.Element,
 options: {
  iconType?: string,
  color?: string,
 }
}
 const Component = ({ title, children, options = {color: '#D3A82B', iconType: 'alert'}: ComponentProps) => {
 return <AnotherComponent color={options.color} iconType={options.iconType}/>
}

Usage:

<Component iconType='danger' />
// default color option is gone
1
  • 1
    Your "usage" doesn't match the ComponentProps you've provided. Your COmponentProps says you're expecting an options prop with color and iconType optional properties, but your usage shows you're expecting color and iconType to be props themselves, not within option....? Commented Jan 24, 2023 at 12:59

2 Answers 2

1

Your "usage" doesn't match the ComponentProps you've provided. Your COmponentProps says you're expecting an options prop with color and iconType optional properties, but your usage shows you're expecting color and iconType to be props themselves, not within option....?

If you meant to have options

It only makes sense to provide a default value for options if options is optional in your component props type; otherwise, the default won't be used since the caller is required to supply options.

If you want to supply defaults for the iconType and color properties of options and also for options itself, you need to mark options optional and then supply defaults for color and iconType (perhaps via destructuring), and also provide an overall default for options (which can be {} if all options have their own defaults):

type ComponentProps = {
    title: string;
    children: React.ReactNode;
    options?: {
        // Added `?` to make `options` optional
        iconType?: string;
        color?: string;
    };
};
const Component = ({
    title,
    children,
    //       vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv−−− defaults for `color` and `iconType`
    options: { color = "#D3A82B", iconType = "alert" } = {},
}: //                                                    ^^−− default for `options` as a whole
ComponentProps) => {
    // ...use `color` and `iconType` here...
};

Live example (with TypeScript types commented out):

/*
type ComponentProps = {
    title: string;
    children: React.ReactNode;
    options?: {
        iconType?: string;
        color?: string;
    };
};
*/
const Component = ({
    title,
    children,
    options: { color = "#D3A82B", iconType = "alert" } = {},
}/*: ComponentProps*/) => {
    return (
        <div>
            color = {color}, iconType = {iconType}
        </div>
    );
};

const Example = () => {

    // No options at all
    const ex1 = <Component title="ex1">ex1</Component>;

    // Just `color`
    const ex2 = <Component title="ex2" options={{color: "blue"}}>ex2</Component>;

    // Just `iconType`
    const ex3 = <Component title="ex3" options={{iconType: "information"}}>ex3</Component>;

    // Both
    const ex4 = <Component title="ex4" options={{color: "blue", iconType: "information"}}>ex4</Component>;

    return (
        <div>
        {ex1}
        {ex2}
        {ex3}
        {ex4}
        </div>
    );
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

If you didn't mean to have options

...then `ComponentProps needs to be flattened a bit, and you just supply the defaults directly:

type ComponentProps = {
    title: string;
    children: React.ReactNode;
    // No `options` layer
    iconType?: string;
    color?: string;
};
const Component = ({
    title,
    children,
    color = "#D3A82B",
    iconType = "alert",
}: ComponentProps) => {
    // ...use `color` and `iconType` here...
};

Live example (with TypeScript types commented out):

/*
type ComponentProps = {
    title: string;
    children: React.ReactNode;
    iconType?: string;
    color?: string;
};
*/
const Component = ({
    title,
    children,
    color = "#D3A82B",
    iconType = "alert",
}/*: ComponentProps*/) => {
    return (
        <div>
            color = {color}, iconType = {iconType}
        </div>
    );
};

const Example = () => {

    // No `color` or `iconType`
    const ex1 = <Component title="ex1">ex1</Component>;

    // Just `color`
    const ex2 = <Component title="ex2" color="blue">ex2</Component>;

    // Just `iconType`
    const ex3 = <Component title="ex3" iconType="information">ex3</Component>;

    // Both
    const ex4 = <Component title="ex4" color="blue" iconType= "information">ex4</Component>;

    return (
        <div>
        {ex1}
        {ex2}
        {ex3}
        {ex4}
        </div>
    );
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

Sign up to request clarification or add additional context in comments.

Comments

0

I have created object with default options called defaultOptions. By doing that i can pass props passed by user into component, as well as spread default options.

export const TOOLTIP_DEFAULT_OPTIONS: TooltipOptions = { color: '#D3A82B', iconType: 'danger' };
    
type ComponentProps = {
 title: string,
 children: JSX.Element,
 options?: {
  iconType?: string,
  color?: string,
 }
}

const defaultOptions = {
    ...TOOLTIP_DEFAULT_OPTIONS,
    ...options,
  };

 const Component = ({ title, children, options = TOOLTIP_DEFAULT_OPTIONS : ComponentProps) => {
 return <AnotherComponent iconType={options.iconType} {...defaultOptions}/>
}

3 Comments

That won't let you supply options with just color or iconType and not the other, as the type of ComponentProps suggests you want to. (Also: Answers with no explanation aren't useful. Say what you did, and why, in order to make an answer useful.)
I have added explanation into my answer. My solution is working for me.
The code in the answer doesn't make sense. First off, what's options' in the object literal you're assigning to defaultOptions? There's no options identifier in scope there. Did you mean for that code to be inside Component? The code also has a syntax error (missing }).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.