#Type narrowing, conditional types

16 messages · Page 1 of 1 (latest)

distant knot
#

If afterFind is defined, the return type should be a merge of schema and afterFind return type.
If afterFind is undefined, the return type should be the schema type.

const schema = { a: 'a' };

function mys<S, T>({ afterFind, schema }: { schema: S; afterFind?: (data: S) => T }) {
  if (afterFind) {
    return afterFind(schema);
  } else {
    return schema;
  }
}

const s1 = mys({ schema });
const s2 = mys({ schema, afterFind: (data) => ({ ...data, b: 'b' }) });

I want s1 to be {a:'a'} and s2 to be {a:'a', b:'b'}
Right now s1 is unknown and s2 is {a: string} | {b: string; a: string;}

umbral gust
#

if afterFind is omitted, its generic can be set to whatever. you'll probably want to overload this

#

or just split this function, or compose it, if possible

distant knot
#

Thanks for the reply,
You mean, have 2 versions of mys function?

#

I am not very good at typescript. Can you show me how would you split or compose mys?

umbral gust
#

yeah, or just wrap the call in afterFind afterwards

#

righto now mys is just kinda useless so i'd just remove it

#

are you doing some processing in your actual code?

distant knot
#

Actually mys is a huge function that returns a tRPC router with basic crud (get/find/create/remove/update), so having 2 versions of it is not possible

#

I tried to experiment with conditional types like `afterFind extends undefined ? ... : ...) but no luck

umbral gust
#

yeah that would not work

umbral gust
#
function base(schema) {
  return getValue(schema);
}

function extra(schema, afterfind)
  return afterfind(base(schema));
}
#

or just pull afterfind to outside the function

distant knot
#

Oh

umbral gust
#
const s2 = { ...mys(schema), b: 'b' }