Tagged template literals - How the gql`query` syntax works
When exploring some graphql I stumbled over it’s quite special syntax for defining a query gql`query`
. Now this seemed like a nice shorthand way of expressing an inline query, but I just couldn’t understand which construct made this possible. Typescript? Ecmascript 2016? Or maybe some other feature?
Here’s an example of a graphql query:
import gql from 'graphql-tag';
const query = gql`
query {
products {
id,
productNumber,
facilityName,
description
}
}
`;
As you see we’re importing the default gql
export from graphql-tag and using it directly when definfing a query.
Then we’re appending a template literals/strings to the import and defining a query to be executed. I’ve omitted the code to actually execute the query, but that isn’t important for this example.
The typescript syntax declaration looks like this:
declare module "graphql-tag" {
function gql(
literals: ReadonlyArray<string> | Readonly<string>,
...placeholders: any[]
): import("graphql").DocumentNode;
Which means that gql
is a function with two parameters.
- A readonly array of strings or a readonly string
- Any number of placeholders (deconstructed array)
But why aren’t we calling gql
in our example above like a function, like this?
import gql from 'graphql-tag';
const query = gql(`
query {
products {
id,
productNumber,
facilityName,
description
}
}
`);
That’s because of a neat feature in Javascript template literals called Tagged template literals. What this means is that a function with the first parameter as a string, and subsequent parameters as arguments, can parse a string literal with template arguments. It can then do logic on the args as it sees fit.
Here’s the example from MDN:
let person = 'Mike';
let age = 28;
function myTag(strings, personExp, ageExp) {
/*Omitted - full example on MDN*/
}
let output = myTag`That ${ person } is a ${ age }`;
So, without digging too much further into details and caveats, this is how graphql can be written as gql`query with ${parameters}`
.