I have a graphene-django GraphQL API that I've added custom directives and middleware in that are very similar to what's offered by graphene-django-extras. There are several places where enum types are returned as a graphene.Int() field, I'd like to be able to use a directive to transform that a graphene.String() but it doesn't do that on its own. eg.
{
foo {
bar # return Int
# vs
bar #readable # return String
}
}
Is that even possible? I'm looking through the ResolvInfo fields and there is something for the return type, but initial attempts don't work.
Edit: FWIW I don't think it matters that the API is currently developed using Python and Graphene. The question is more about whether or not GraphQL even supports this, I assume that if it does not then no language or library would make it possible.
It's not really in the spirit of graphQL to have a variable output type. So strictly speaking, you shouldn't try to do this. That being said, instead you could easily add another field for the other type, i.e.
type Foo {
barStr: String
barInt: Int
}
and then just ask for the one that you want in your query.
I am trying to have a "generic" info in my object.
Basically what I want to do is to have 2 different kinds of object, lets say image and document
Both have different fields except for the ID
I was wondering what would be the best approach to define my datamodel.prisma so when I use my graphql model (in GO) I can use a generic interface like data
Is it even possible? If not what solution could be the best?
I know in graphql there are interfaces but Im not sure how to define it in prisma.
Ideas?
Interface and union types are not currently supported in Prisma (see feature requests here and here).
I am using the Apollo Server implementation of GraphQL, together with the Apollo Engine, and specifically the functionality to check whether a schema diff contains any breaking changes. I'd like to understand better why TYPE_ADDED_TO_INTERFACE is considered to be a breaking change, and if anyone can provide an example of a graphql query that would break, as a consequence?
I'm using the apollo/2.9.0 darwin-x64 node-v10.10.0 to perform the schema check with the apollo service:check command.
For example, if I have this schema:
interface Animal {
id: ID
}
type Dog implements Animal {
id: ID
favoriteToy: String
}
And then add this to the schema:
type Cat implements Animal {
id: ID
}
This is considered a breaking change. Why?
I can see that if someone is making a query for all the Animal objects, and has a ... on Dog fragment in the query, they would start getting Cat objects back with only the interface fields, until they also add a ... on Cat fragment. Is that what's considered breaking?
Having a type implement an interface it previously did not should not break existing queries. To your point, even if the inline fragment is omitted, the results will still be valid (they could result in an empty object being returned if no interface fields were selected, but that's still a valid response).
I could, however, foresee issues in specific clients resulting from this kind of change. For example, when using Apollo client, we often create an IntrospectionFragmentMatcher to specifically help the client correctly cache results from union or interface fields.
To support result validation and accurate fragment matching on unions and interfaces, a special fragment matcher called the IntrospectionFragmentMatcher can be used. If there are any changes related to union or interface types in your schema, you will have to update the fragment matcher accordingly.
In other words, having the schema change in this way could break client caching behavior. I suspect for clients that do schema-based code-generation, like apollo-android, this could also result in some runtime weirdness.
I've been looking around to see if a pattern exists for merging two graphQL datasets which contain the same type of data. What I mean is, given the following two type definitions;
type StevesBooks {
title: String
author: String
}
type DavesBooks {
title: String
author: String
}
If both of those are implemented as graphQL schemas separately/remotely, each with their own set of resolvers, is there a pattern or paradigm I can draw from to create a third graphQL instance that combines these two, so I can query "SteveAndDavesBooks" at the same time?
I found mergeSchemas in the apolloServer API but that solves a different problem to this one and all of the conflict-resolution methods in there require you to "choose a side" so to speak, rather than combine the results.
Is there already-written plugin or library somewhere that will help to achieve the above or do you think this is going to be something bespoke that I need to do myself?
I saw that query federation is on the roadmap - does anyone know any more details about that because that sounds like what I'm after.
I read through the TypeScript Coding guidelines
And I found this statement rather puzzling:
Do not use "I" as a prefix for interface names
I mean something like this wouldn't make a lot of sense without the "I" prefix
class Engine implements IEngine
Am I missing something obvious?
Another thing I didn't quite understand was this:
Classes
For consistency, do not use classes in the core compiler pipeline. Use
function closures instead.
Does that state that I shouldn't use classes at all?
Hope someone can clear it up for me :)
When a team/company ships a framework/compiler/tool-set they already have some experience, set of best practices. They share it as guidelines. Guidelines are recommendations. If you don't like any you can disregard them.
Compiler still will compile your code.
Though when in Rome...
This is my vision why TypeScript team recommends not I-prefixing interfaces.
Reason #1 The times of the Hungarian notation have passed
Main argument from I-prefix-for-interface supporters is that prefixing is helpful for immediately grokking (peeking) whether type is an interface. Statement that prefix is helpful for immediately grokking (peeking) is an appeal to Hungarian notation. I prefix for interface name, C for class, A for abstract class, s for string variable, c for const variable, i for integer variable. I agree that such name decoration can provide you type information without hovering mouse over identifier or navigating to type definition via a hot-key. This tiny benefit is outweighed by Hungarian notation disadvantages and other reasons mentioned below. Hungarian notation is not used in contemporary frameworks. C# has I prefix (and this the only prefix in C#) for interfaces due to historical reasons (COM). In retrospect one of .NET architects (Brad Abrams) thinks it would have been better not using I prefix. TypeScript is COM-legacy-free thereby it has no I-prefix-for-interface rule.
Reason #2 I-prefix violates encapsulation principle
Let's assume you get some black-box. You get some type reference that allows you to interact with that box. You should not care if it is an interface or a class. You just use its interface part. Demanding to know what is it (interface, specific implementation or abstract class) is a violation of encapsulation.
Example: let's assume you need to fix API Design Myth: Interface as Contract in your code e.g. delete ICar interface and use Car base-class instead. Then you need to perform such replacement in all consumers. I-prefix leads to implicit dependency of consumers on black-box implementation details.
Reason #3 Protection from bad naming
Developers are lazy to think properly about names. Naming is one of the Two Hard Things in Computer Science. When a developer needs to extract an interface it is easy to just add the letter I to the class name and you get an interface name. Disallowing I prefix for interfaces forces developers to strain their brains to choose appropriate names for interfaces. Chosen names should be different not only in prefix but emphasize intent difference.
Abstraction case: you should not not define an ICar interface and an associated Car class. Car is an abstraction and it should be the one used for the contract. Implementations should have descriptive, distinctive names e.g. SportsCar, SuvCar, HollowCar.
Good example: WpfeServerAutosuggestManager implements AutosuggestManager, FileBasedAutosuggestManager implements AutosuggestManager.
Bad example: AutosuggestManager implements IAutosuggestManager.
Reason #4 Properly chosen names vaccinate you against API Design Myth: Interface as Contract.
In my practice, I met a lot of people that thoughtlessly duplicated interface part of a class in a separate interface having Car implements ICar naming scheme. Duplicating interface part of a class in separate interface type does not magically convert it into abstraction. You will still get concrete implementation but with duplicated interface part. If your abstraction is not so good, duplicating interface part will not improve it anyhow. Extracting abstraction is hard work.
NOTE: In TS you don't need separate interface for mocking classes or overloading functionality.
Instead of creating a separate interface that describes public members of a class you can use TypeScript utility types. E.g. Required<T> constructs a type consisting of all public members of type T.
export class SecurityPrincipalStub implements Required<SecurityPrincipal> {
public isFeatureEnabled(entitlement: Entitlement): boolean {
return true;
}
public isWidgetEnabled(kind: string): boolean {
return true;
}
public areAdminToolsEnabled(): boolean {
return true;
}
}
If you want to construct a type excluding some public members then you can use combination of Omit and Exclude.
Clarification regarding the link that you reference:
This is the documentation about the style of the code for TypeScript, and not a style guideline for how to implement your project.
If using the I prefix makes sense to you and your team, use it (I do).
If not, maybe the Java style of SomeThing (interface) with SomeThingImpl (implementation) then by all means use that.
I find #stanislav-berkov's a pretty good answer to the OP's question. I would only share my 2 cents adding that, in the end it is up to your Team/Department/Company/Whatever to get to a common understanding and set its own rules/guidelines to follow across.
Sticking to standards and/or conventions, whenever possible and desirable, is a good practice and it keeps things easier to understand. On the other side, I do like to think we are still free to choose the way how we write our code.
Thinking a bit on the emotional side of it, the way we write code, or our coding style, reflects our personality and in some cases even our mood. This is what keeps us humans and not just coding machines following rules. I believe coding can be a craft not just an industrialized process.
I personally quite like the idea of turning a noun into an adjective by adding the -able suffix. It sounds very impropper, but I love it!
interface Walletable {
inPocket:boolean
cash:number
}
export class Wallet implements Walletable {
//...
}
}
The guidelines that are suggested in the Typescript documentation aren't for the people who use typescript but rather for the people who are contributing to the typescript project. If you read the details at the begging of the page it clearly defines who should use that guideline. Here is a link to the guidelines.
Typescript guidelines
In conclusion as a developer you can name you interfaces the way you see fit.
I'm trying out this pattern similar to other answers, but exporting a function that instantiates the concrete class as the interface type, like this:
export interface Engine {
rpm: number;
}
class EngineImpl implements Engine {
constructor() {
this.rpm = 0;
}
}
export const createEngine = (): Engine => new EngineImpl();
In this case the concrete implementation is never exported.
I do like to add a Props suffix.
interface FormProps {
some: string;
}
const Form:VFC<FormProps> = (props) => {
...
}
The type being an interface is an implementation detail. Implementation details should be hidden in API:s. That is why you should avoid I.
You should avoid both prefix and suffix. These are both wrong:
ICar
CarInterface
What you should do is to make a pretty name visible in the API and have a the implemtation detail hidden in the implementation. That is why I propose:
Car - An interface that is exposed in the API.
CarImpl - An implementation of that API, that is hidden from the consumer.