typescript - Hur kan jag korrekt typa context-objektet i Apollo Server?
Jag använder Apollo Server med TypeScript och jag har problem med att få context-parametern inne i min resolver att förstå att name-egenskapen på context är en sträng. Just nu är den typad som any och jag skulle vilja att den var typad som string. Jag ser också att context-parametern är av typen any, när jag skulle vilja att den var ett specifikt gränssnitt. Finns det något sätt att tala om för context och dess egenskaper vilken typ jag vill att de ska ha istället för att de alla typas som any?
const server = new ApolloServer({
typeDefs: gql`
type Query {
test: String
}
`,
resolvers: {
Query: {
test(parent: any, args: any, context, info: any) {
context.name // name is typed as "any" when I'd like it to be typed as "string"
}
}
},
context() {
return {
name: 'John Doe'
}
}
})
Jag försökte göra något liknande, men det ger ett fel.
context<{ name: string }>() {
return {
name: 'John Doe'
}
}
Jag fick det att fungera genom att uttryckligen tala om för context vad det behöver vara, men det här sättet verkar lite jobbigt eftersom jag måste importera Context i varje resolver-fil och göra en manuell typomvandling.
interface Context {
name: string
}
const server = new ApolloServer({
...
resolvers: {
Query: {
test(parent: any, args: any, context: Context, info: any) {
context.name // name is typed as "string" here because I used "context: Context" explicitly
}
}
}
...
})
Svar #1
Om du använder graphql-code-generator för att generera dina typer kan du konfigurera kontexttypen i codegen.yml:
generates:
src/generated/graphql.ts:
config:
contextType: "src/types#Context"
Definiera sedan din kontexttyp:
export interface Context {
username: string;
}
Nu kommer context-argumentet i dina resolver-metoder att ha typen Context utan att du behöver importera typer eller göra några andra ändringar.
Svar #2
Som standard är fältet resolvers på Config-objektet du ger till ApolloServer öppet för alla typer, men du kan använda TypeScript för att göra din egen typavgränsning.
Som referens accepterar ApolloServer en instans av eller en array av IResolvers-objekt som deklareras här: https://github.com/apollographql/apollo-server/blob/a241d34e9275bf6a23cf7aa3ddee57f90de7b364/packages/apollo-server-core/src/types.ts#L90. IResolvers har generiska typparametrar, men dessa har som standard any: https://github.com/ardatan/graphql-tools/blob/8c8d4fc09ddc63c306db16d7386865ac297794bd/packages/utils/src/Interfaces.ts#L298. I ditt kodexempel är Query en av de specifika typer som utgör IResolvers och test() implementerar IFieldResolver: https://github.com/ardatan/graphql-tools/blob/8c8d4fc09ddc63c306db16d7386865ac297794bd/packages/utils/src/Interfaces.ts#L236.
Du kan dra nytta av det faktum att IResolvers har generiska parametrar för att begränsa typen av context-argumentet. Till exempel, genom att uttryckligen specificera en typ på vänster sida av en tilldelning, kan du tala om för kompilatorn vad som förväntas på höger sida:
interface Context {
username: string
}
const myResolvers: IResolvers<any, Context> = {
Query: {
test: (parent, args, context) => {
console.log(context.username) // based on generics TS knows context is supposed to be of type Context
}
}
}
new ApolloServer({
...
resolvers: myResolvers,
...
