0

I would like to define type when destructuring an array, But it shows some error:

interface buildTargetProps {
  target: string;
  path: string;
}
interface buildTargets {
  [property: string]: buildTargetProps
};


const ChooseApp: buildTargets = {
  'autocomplete': {
    target: "test",
    path: "./Autocomplete",
  },
  'search': {
    target: "search-root",
    path: "./Search",
  },
};


let [applicationToBuild] = Object.entries(ChooseApp).find(
  ([name, props]: [String, buildTargetProps]) => {
    if (document.getElementById(props.target)) {
      return name;
    }
  }
);

What I want to do is defined the type of "applicationToBuild" variable, for that I have Tried:

let [applicationToBuild]: [string] | undefined  = Object.entries(ChooseApp)

I intentionally skipped the other array element, as I don't need that, But I tried to add that as well, to check if that resolves the error, But that also didn't work.

let [applicationToBuild, otherprops]: [string, buildTargetProps] | undefined  = Object.entries(ChooseApp)

But, this throws an error.

Type '[string, buildTargetProps] | undefined' is not assignable to type '[string] | undefined'.
  Type '[string, buildTargetProps]' is not assignable to type '[string]'.
    Source has 2 element(s) but target allows only 1.ts(2322)
Type '[string] | undefined' is not an array type.ts(2461)
3
  • There are two issues: 1. find does not return an array, instead a single value. In your case it is a string. So, no need of boxes around [applicationToBuild]. 2. You are not explicitly returning anything if if condition fails. See this: tsplay.dev/1WG7VW Commented Jan 26, 2021 at 14:01
  • 1. find returns an array, although I returned name, it returns an array of key and value when found, ['autocomplete', {target: "test",path: "./Autocomplete",}] otherwise undefined. from the array, I want just the key which is autocomplete and want to define that it should be of type string. Commented Jan 26, 2021 at 14:09
  • 1
    Oops my bad. I take it back. Commented Jan 26, 2021 at 14:12

1 Answer 1

1

You are iterating on the entries of the JSON object. Essentially, you are dealing with an array of tuples that looks like this:

[ 
  [ 
    'autocomplete', 
    {
      target: "test",
      path: "./Autocomplete",
    }
  ],
  [
    'search',
    {
      target: "search-root",
      path: "./Search",
    }
  ]
]

The .find function returns the first object that matches the criteria (one that return a truthy value) provided in the callback function. So, it returns the tuple of the shape [string, {target: string, path: string}]. But, in case it does not match anything it returns undefined. And, that's where the problem is. In case where returns undefined, the destructure won't work. So, you return an empty array just to make sure the destructure work and the value is assigned to undefined.

Here is a shorter version:

interface buildTargetProps {
  target: string;
  path: string;
}
interface buildTargets {
  [property: string]: buildTargetProps
};


const ChooseApp: buildTargets = {
  'autocomplete': {
    target: "test",
    path: "./Autocomplete",
  },
  'search': {
    target: "search-root",
    path: "./Search",
  },
};


let [applicationToBuild] = Object
  .entries(ChooseApp)
  .find(
    ([_, props]) => !!document.getElementById(props.target)
  ) || 
  [];

console.log(applicationToBuild)

TS Playground

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.