简体   繁体   中英

Typescript autocomplete for return type of function

I am trying to create a simply function what would return value of object by key and, if it is a function, it would execute it and return correct type, so it can be autocompleted by code editor.

type defaults = {
  a: "A" | "B" | (() => "A" | "B");
  b: "X" | "Y" | (() => "X" | "Y");
};

const myOpts: defaults = {
  a: () => "A",
  b: () => "X",
};

function option(name: string) {
  if (!myOpts[name]) {
    return null;
  }

  return typeof myOpts[name] === "function"
    ? myOpts[name].call()
    : myOpts[name];
}

console.log(myOpts.a);      // Autocomplete works
console.log(option("a"));   // Autocomplete does not work at all
console.log(option("xyz")); // Should warn that it does not exist!!!

So, is it possible to tell that the return type of the function is the type of value that is found by key in some object.

So, I'm assuming you just want to have auto completion for anything that can be deduced from the type, in that case, you could just use the keyof operator

In your scenario, you would change the option function to:

function option(name: keyof defaults): 'A' |'B' | 'X' | 'Y' | null {
  const prop = myOpts[name];
  if (!prop) {
    return null;
  }

  if (typeof prop === 'function') {
    return prop();
  }
  return prop;
}

Which would give you a warning, if you try to use an unknown key as an argument.

Now the last change that was needed, was to change how the potential function would be called. You could use prop.call( null ) here as well, but why not directly call it instead (if you are anyhow sure it's a function as checked before)

You can try it in the playground here

As a remark, based on the type inference, the current function wouldn't actually return null; anywhere now (it will always be any of the non-nullable properties) but I added the null function result to not have to change to much of your code:)

Another option of changing your code would be to use some more generic option, say:

function option<T>( source: T, name: keyof T): any {
  const prop = source[name];
  if (!prop) {
    return null;
  }

  if (typeof prop === 'function') {
    return prop();
  }
  return prop;
}

which would still give you validation, but the result type will probably need to be any at that time, or string if you always intend to return string values from it

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM