Fred Hors
Fred Hors

Reputation: 4156

How can I correctly type functions in object using Typescript here?

I'm converting a JS project to TS and here I have this error (using urql):

A function whose declared type is neither 'void' nor 'any' must return a value. ts(2355) on line:

playerCreate: (result, args, cache): UpdateResolver => {

Why?

const updates = {
  Mutation: {
    playerCreate: (result, args, cache): UpdateResolver => {
      const playersQueries = cache
        .inspectFields("Query")
        .filter((x) => x.fieldName === "players");
      playersQueries.forEach(({ fieldName, arguments: variables }) =>
        cache.invalidate("Query", fieldName, variables)
      );
    },

    playerDelete: (result, args, cache, info): UpdateResolver => {
      // using result, args, cache here
    },
  },
};

I can see Updateresolver is declared like this:

export declare type UpdateResolver = (result: Data, args: Variables, cache: Cache, info: ResolveInfo) => void;

UPDATE:

Someone rightly told me that I'm saying that this function returns an UpdateResolver while the type is for the function not the return-type.

Hence the question:

How can I correctly type here playerCreate and playerDelete?

Upvotes: 0

Views: 207

Answers (1)

blaumeise20
blaumeise20

Reputation: 2220

Try to change the code to this:

const updates = {
  Mutation: {
    playerCreate: (result: Data, args: Variables, cache: Cache): void => {
      const playersQueries = cache
        .inspectFields("Query")
        .filter((x) => x.fieldName === "players");
      playersQueries.forEach(({ fieldName, arguments: variables }) =>
        cache.invalidate("Query", fieldName, variables)
      );
    },

    playerDelete: (result: Data, args: Variables, cache: Cache, info: ResolveInfo): void => {
      // using result, args, cache here
    },
  },
};

EDIT: I've found out that it is actually possible by using the as operator:

const updates = {
  Mutation: {
    playerCreate: (((result, args, cache) => {
      const playersQueries = cache
        .inspectFields("Query")
        .filter((x) => x.fieldName === "players");
      playersQueries.forEach(({ fieldName, arguments: variables }) =>
        cache.invalidate("Query", fieldName, variables)
      );
    }) as UpdateResolver),

    playerDelete: (((result, args, cache, info) => {
      // using result, args, cache here
    }) as UpdateResolver),
  },
};

What is the as operator in TypeScript?

It tells the TypeScript compiler to think that the expression before the operator has the type after the operator. You can do some weird things with it:

const test = "some string" as number;
// "test" is number here!!

So be careful where you use it! When you apply it to functions, TypeScript will see that e. g. parameter one should have type T, so it pretends, that the function also takes a parameter of type T.

There is an alternative to as, but it cannot be used in TSX files:

const something = <number>"hello";
// don't do that if you don't know the actual type!

Of course this example is wrong, because TypeScript will think that the string is a number, but it isn't. But it shows the usage of the type assertion.

Upvotes: 3

Related Questions