I work on TypeSpec. I'll be around if anyone has questions!
HN user
bterlson
Working @ Microsoft on Azure, TS/JS, TypeSpec.
You can get by, e.g. you can use JSDoc comments describing format or pattern, generic types taking a parameter of either format or pattern along with a base type, or create a custom well-known type you define as having the properties of a UUID. But aside from comments, this is not reflected well in the tooling, and none of these options compose particularly well.
It is being worked on. The best place to follow the development is our discord, there's a channel for graphql.
We first tried a TypeScript DSL and I really wish it would have worked for our use cases (e.g. describing complex REST APIs in Azure), but unfortunately it didn't.
I explained a bit more here last time TypeSpec was on here: https://news.ycombinator.com/item?id=39843184
As someone who works on TypeSpec, my feeling is that they are mostly different things. TypeSpec is a general purpose DSL which supports "emitting" to protobuf and other things, but in and of itself doesn't prescribe any particular protocol or serialization format.
There are a few emitters in our standard library - OpenAPI 3.0, JSON Schema 2020-12, and Protobuf. REST client and service emitters for a few languages are coming online now and should be ready in the next couple months.
I think it can be, but it can also be used with OpenAPI to great effect as well. We're not trying to replace OpenAPI, OpenAPI is great in many ways and is useful for many people. In general we believe strongly in being interoperable with the existing API description ecosystem.
TypeSpec is designed primarily as an API first tool as opposed to being an output. In the context of ASP.NET and HTTP/REST APIs, our goal is that you can write your spec and generate much of the service implementation and clients. From this same source of truth you could also emit clients or service implementations in other API definition formats like OpenAPI, schemas like JSON Schema, and other things besides.
The OpenAPI and Json Schema emitters can produce yaml.
Yup, similar to that specific piece, and I definitely agree that GraphQL's DSL shows how much the DX of the description language itself matters, and how codegen is a productivity multiplier. I think gRPC also demonstrates this. You can think of TypeSpec as an attempt to bring these benefits to any protocol, schema vocabulary, or programming language.
Moreover, compiling an IDL to N languages is substantially easier than compiling implementation code across N languages, especially when generating idiomatic code is a requirement. A language purpose-built for this task is going to produce better results while having substantially lower complexity.
(My $0.02 as someone who works on TypeSpec)
(I work on the team)
I wouldn't say that TypeSpec is like GraphQL, so it would be hard for TypeSpec to become that on its own. GraphQL has a lot of opinions that are required in order to build a concrete application (protocols, error handling, query semantics, etc.), whereas TypeSpec at its core is just an unopinionated DSL for describing APIs. Bindings for particular protocols are added via libraries, and a GraphQL library is something we have long considered.
So in short, if Microsoft invented a set of opinions that solved similar scenarios to GraphQL, it might use TypeSpec as the API description language in that context, but it wouldn't be fair to equate those opinions with TypeSpec itself.
Grats on the release! It will be awesome to see how far y'all can push codegen quality from an OpenAPI source of truth.
I worked on this extensively inside Azure and I know it is not an easy problem (and with more JSON Schema coming in 3.1/4.0, it is only getting harder). There are a lot of API patterns that you want to expose purpose built client abstractions for. Pagination is a big example. If you stick to OpenAPI, you have to ensure your specs use the patterns your client generator recognizes, and it's not always trivial for authors to know how to express that pattern and for your codegen to infer that pattern. In Azure we tended to rely more on custom extensions to OpenAPI because it made the contract a lot clearer and less error prone, but then you lose interoperability.
One thing to consider - I work on TypeSpec[1], and one of the main reasons we built it is to allow encapsulation and reuse of patterns in a first-class way. So, rather than the contract being "endpoints which declare parameters and/or return types with these shapes are inferred to be paginated endpoints", the contract can be "use Page<T>" and the emitted OpenAPI conforms to the contract without effort. It would be fun to see a Stainless TypeSpec library for all the patterns your codegen supports!
I'm just a JS guy trying to understand the world around me and documenting what I find, not trying to be discourteous (or even courteous). I'll add the note about Python, thanks for calling it out. FWIW JS does not have a similar capability so I can't add a note there.
Pedantically, IEEE 754 defines decimal floating point formats (like decimal128) which are appropriate for representing currency. Representing currency in non-integer values in any of the binary floating point formats is indeed a recipe for disaster though.
If you would like to contribute Swift tests, I would be happy to take it! You can send a PR into this document, updating the data tables and adding a code sample at the end: https://github.com/bterlson/blog/blob/main/content/blog/what.... No need to test openapi-tools swift codegen unless you really want to!
JS is likely to get a hook to be able to handle serialization/deserialization of such values without swapping out the entire implementation[1]. Native support for these types, without additional code or configuration, would likely break the Internet badly, so is unlikely to happen unfortunately.
I think the spec just means, assume IEEE 754. In the case of 0.1, which cannot be represented exactly, software should assume that `0.1` will be represented as `0.100000000000000005551115123126`. Depending on `0.1` being parsed as the exact value `0.1` is not widely interoperable.
I have added this note, thanks! In the blog I am mostly trying to show the behavior you get using the (maybe defacto) stdlib with its default configuration, but this is useful data to call out.
We're working on bringing it into the TypeSpec project as we speak. You can see an initial demo of it working in this repo: https://github.com/bterlson/typespec-todo.
The link should load up with a sample I wrote, I think? It does for me anyway! Let me know if you don't see it. But I'll also paste it here:
model Foo {
/** this is a description */
x: Bar;
}
/** this is also a description */
model Bar {}The playground I posted has a description. They're pulled from JSDoc style comments. You can also use the `@doc` decorator, though that's usually reserved for more advanced cases like when you need string interpolation or something.
By the way, you can use the "allOf hack" to put documentation alongside a ref. TypeSpec emits this for common cases like this one:
https://typespec.io/playground?c=bW9kZWwgRm9vIHsNCiAgLyoqIHR...
For what it's worth, we support 3.0 because as you note the ecosystem doesn't support 3.1 broadly yet. I'm personally interested to see if 3.1 becomes prevalent before 4.0 is released. Maybe the ecosystem will just skip 3.1?
We generate OAS because it's useful for many folks, including for us in Azure. But like you we didn't have very good luck getting high quality codegen from OpenAPI. Our latest client codegen tech doesn't use OpenAPI, we generate code directly from the TypeSpec, which offers a number of advantages that result in higher quality. Probably at topic for a blog of its own! Anyway, you might be happy to know that we are working on bringing our emitters into the TypeSpec project so anyone can use it with their TypeSpecs.
This docs page will hopefully help:
It's a beauty! I had to get on the train early before it's everywhere.
Not yet, but we're working on it. Should be out in a few weeks.
It does not exist, but it will be worked on fairly soon. You can track progress on GitHub [1]. It will be as you suggest - a one time conversion, after which you can iterate. We have this workflow for inside Azure, but the converter is Azure-specific (e.g. converts to TypeSpec that uses our extensive Azure-specific component library). It will take a bit to generalize.
Codegen is coming online as we speak. We do codegen from TypeSpec in Azure across multiple languages, and the results are pretty great. We're moving that over to the TypeSpec project so everyone can generate code. Obviously my opinion is biased, but I think the results are significantly better than what you find elsewhere in the ecosystem.
Extensive experience inside Azure. In general, supporting existing APIs is harder, predominantly because it might not sufficient to produce a semantically identical OpenAPI when downstream tools are sensitive to e.g. whether something is a ref or not, the order of properties in the document, whether something uses `const` or an `enum` with a single member, etc.
If you have more specific questions I'm happy to consult!