Introduction
This tutorial will walk you will walk you thru using a web browser to write some TypeScript code to access a couple free online APIs.
Prerequisites
To take full advantage of the topics covered in this tutorial you should have some familiarity with the following concepts:
- Submitting form data on a webpage
- Examining the web browser console
- Basic programming knowledge
- JavaScript
Jamstack
It is somewhat generally accepted that the LAMP stack began in 1995 and continues to be a dominant force behind serving web pages. A stack is just another way to say “software bundle”.
LAMP is an acronym which stands for:
L – Linux (operating system kernel)
A – Apache (web server)
M – MySQL (relational database)
P – PHP / Perl / Python (programming language)
While the LAMP stack is used on the “back-end” server-side of a web system, the Jamstack is primarily focused on the “front-end” client-side offloading data and services to various APIs. This is a good way to architect and scale systems especially when used within the Microservice Architecture pattern.
Jamstack is not an acronym but the Jam part can be thought of as:
J – JavaScript (programming language)
A – APIs (service distribution)
M – Markup (HTML / CSS)
According to Chris Richardson’s Scale Cube, it is good to split up different parts of your system into separate microservices. This is called functional decomposition and each microservice then has its own API call.
From the jamstack.org website:
When we talk about “The Stack”, we no longer talk about operating systems, specific web servers, back-end programming languages, or databases.
The Jamstack is not about specific technologies. It’s a new way of building websites and apps that delivers better performance, higher security, lower cost of scaling, and better developer experience.
Pre-rendered sites can be enhanced with JavaScript and the growing capabilities of browsers and services available via APIs.
The take-away here is that when building stuff for the web the state of the art technology involves JavaScript and APIs.
What is an API?
When we’re talking about web APIs we’re usually talking about a Representational State Transfer API or “RESTful” API or just REST API for short. According to Roy Fielding, a REST API is a cacheable, stateless, uniform, client-server interface layered in a way that one piece does not know or even care about what another piece is doing.
A REST API endpoint contains two main components:
- URL – e.g.
http://rapidapi.com
- HTTP method – e.g.
GET
API is an acronym that stands for Application Programming Interface. That means it is an interface for programming applications. You can think of an API as a set of commands, usually URLs, that we can request to get what we want.
Let’s take each of these three terms and break them down.
Application
An application in the narrow sense means software application. It might be displayed in a web browser and show the user text, images, and form elements. In the broader sense, an API answers the question: “How do we apply for what we want?”
Programming
Programming an application means writing one or more text files in the programming language. These text files list the set of instructions and constitute the “program” that will call the APIs. We will use the TypeScript programming language.
Interface
An interface is a boundary between two things. In our case, it is the boundary between the application and the outside data & services. This boundary has a certain shape and you must know the exact shape before you can go beyond it. For example, the user list endpoint might contain the path /users
, but the path /userlist
or some other similar path might not work.
How to make an API call
In this tutorial, we will focus on just client-side web APIs (not server-side). We will need an HTTP client (web browser) to access three (3) online apps. These apps will request our API URLs and accept the responses:
- RapidAPI – Graphical user interface (GUI)
- Codepen – JavaScript source code executed from a web page
- Playground – TypeScript source code executed from a web page
Testing the API
We’re going to use the Crypto Asset Market Data API from BlockFacts to check Bitcoin prices on a few different exchanges. BlockFacts offers the API for free but requires us to use an API/secret key pair so they can identify who is making a request. This is important to shut someone down if they violate any of the terms of service like too many requests too quickly, for example.
Connect to the Blockfacts.io API
RapidAPI
The easiest way to get started is to open up a web browser, signup for a free account with RapidAPI and head over to the dashboard:
Exchanges
Firstly, let’s get a list of exchanges where we can find Bitcoin data.
In the endpoints panel on the left under the BlockFacts Normalized Data group select the Exchanges in normalization endpoint:
Under the Header Parameters section fill in the following two required pieces of data:
X-API-KEY
X-API-SECRET
These headers get sent to BlockFacts. The values are supplied for us to easily copy & paste:
Notice that RapidAPI has their own required key which should already be filled in for us:
X-RapidAPI-Key
Now scroll back up and click the blue Test Endpoint button to execute your query request:
Look in the Results panel for the response Body. We should have received at least one item containing a list of Bitcoin exchanges (your results may vary):
KRAKEN
COINBASE
BITSTAMP
GEMINI
Current Trading Price
Now let’s check the current price on Kraken.
In the endpoints panel on the left under the Exchange Data group select the Current trade data endpoint:
All the header information should still be filled in from the last http request we made.
In the Required Parameters section we want to inquire about the Bitcoin (BTC) asset with the US dollar (USD) denominator.
Under the Optional Parameters section we want the Kraken exchange.
Click the blue Test Endpoint button:
With our successful response we should get something in the Results panel / response Body / price field. When I ran it I got 9157.2
which means Kraken is currently trading at $9,157.20 US dollars per Bitcoin. When you run it your values are sure to be different.
Connect to the Blockfacts.io API
Codepen
Now instead of using the RapidAPI dashboard let’s try and issue the last price request using JavaScript in Codepen.
Head over to https://codepen.io/pen/?editors=0012 and type in the following JavaScript in the JS window:
const query = { asset: "BTC", exchange: "Kraken", denominator: "USD", }; const url = new URL('https://crypto-asset-market-data-unified-apis-for-professionals.p.rapidapi.com/api/v1/exchanges/trades'); url.search = new URLSearchParams(query).toString(); const headers = { "x-api-key": "[insert-your-api-key]", "x-api-secret": "[insert-your-api-secret]", "x-rapidapi-host": "crypto-asset-market-data-unified-apis-for-professionals.p.rapidapi.com", "x-rapidapi-key": "REPLACE_THIS_WITH_YOUR_KEY", }; (async function () { const response = await fetch( url.toString(), {headers} ); const data = await response.json(); console.log(data) })()
Note: Instead of copying & pasting the source code, a good way to learn is to actually type in the statements manually. The complex API keys in the headers variable would be valid exceptions and it’s probably better to copy/paste to get them right.
Make sure that you check all the entries in the headers variable so that they match the values that you have on your RapidAPI dashboard.
The code should automatically execute and display the results in the Console:
When I run it I get back the following JSON data in the browser console:
{ "BTC-USD": [ { "exchange": "KRAKEN", "pair": "BTC-USD", "price": 9141.3, "tradeSize": 1, "denominatorSize": 9141.3, "makerTaker": "sell", "tradeId": "", "exchangeTime": "1593459206.441408", "blockfactsTime": 1593459206298, "epochExchangeTime": 1593459206441 } ] }
So far we have experimented with calling an API using a graphical user interface (RapidAPI) and also using some JavaScript code. Now let’s try it with TypeScript.
What is TypeScript?
JavaScript at scale. Any browser, Any host, Any OS. Open source.
TypeScript is a strict typed superset of ECMAScript that compiles to plain JavaScript.
The source files are typically named with the extension .ts
for example, hello-world.ts
might be the name of a Hello World script.
History
In 2010 Microsoft wanted to leverage the features of JavaScript but found its weak dynamic typing detrimental “at scale”. Problems became easy to create and hard to detect when the application grew very large.
They considered creating a new language. They also noted that ECMAScript version 5 was on track to align with international standards. Seeing this as a sign of future adoption, Microsoft chose to create a superset of JavaScript.
TS > JS
A JavaScript program is always a TypeScript program; but, a TypeScript program is NOT always a JavaScript program. In other words straight JavaScript will compile seamlessly as TypeScript. But TypeScript will first need to be compiled into plain JavaScript before it can run in the browser or with Node.js.
What this means is that TypeScript does everything that JavaScript does and more. The most notable addition is the optional support for static typing. It is probably the main thing that Microsoft wanted out of their new language.
Static Typing
Static type checking enforces rules during development as opposed to during run-time. In addition to other type annotations each function in the program defines a signature that callers must adhere to. For example when a function expects an argument to be a number and you call it with a string then the TypeScript compiler will complain.
TypeScript supports the following basic types:
Other Features
The type ecosystem, in addition to functions, also includes:
- literals,
- guards,
- aliases,
- assertions,
- interfaces,
- inferences,
- intersections,
- unions,
- singletons,
- utility types,
- index types,
- mapped types,
- conditional, types,
- polymorphic types,
- enum members and
- structural subtyping.
Other language features include:
- classes,
- generics,
- generators,
- iterators,
- decorators,
- directives,
- mixins,
- modules,
- namespaces,
- symbols and
- support for JSX.
JSX
“JSX is an embeddable XML-like syntax. It is meant to be transformed into valid JavaScript, though the semantics of that transformation are implementation-specific. JSX rose to popularity with the React framework, but has since seen other implementations as well. TypeScript supports embedding, type checking, and compiling JSX directly to JavaScript.” —TypeScript Handbook
// Using JSX to express UI components. var dropdown = <Dropdown> A dropdown list <Menu> <MenuItem>Do Something</MenuItem> <MenuItem>Do Something Fun!</MenuItem> <MenuItem>Do Something Else</MenuItem> </Menu> </Dropdown>; render(dropdown);
From the JSX Specification:
JSX is an XML-like syntax extension to ECMAScript without any defined semantics. It’s NOT intended to be implemented by engines or browsers… It’s intended to be used by various preprocessors (transpilers) to transform these tokens into standard ECMAScript.
Testing the API
Let’s get back to the source code and try our API call in the TypeScript Playground.
Connect to the Blockfacts.io API
Playground
Head over to https://www.typescriptlang.org/play/ and type in the same code as from the Codepen section:
Don’t forget to make sure that you check all the entries in the headers variable so that they match the values that you have on your RapidAPI dashboard.
Run JavaScript
Press the Run button and check your browser’s console because fetch runs asynchronously and the log output might not appear in the Playground app Logs:
When I run it I get back the following JSON data in the browser console:
{ "BTC-USD": [ { "exchange": "KRAKEN", "pair": "BTC-USD", "price": 9111, "tradeSize": 0.01092144, "denominatorSize": 99.50523983999999, "makerTaker": "buy", "tradeId": "", "exchangeTime": "1593450280.772280", "blockfactsTime": 1593450280627, "epochExchangeTime": 1593450280772 } ] }
Arrow Function
Before we get too deep into TypeScript let’s get our feet wet by converting our closure function to an arrow function.
Change this:
(async function () { const response = await fetch( url.toString(), {headers} ); const data = await response.json(); console.log(data) })()
To this:
(async () => { const response = await fetch( url.toString(), {headers} ); const data = await response.json(); console.log(data) })()
Does it still run? It should.
Typed Function
Now let’s rearrange things a little to take advantage of TypeScript’s type annotations. Pull the fetch call out and put it into a separate function so that we can declare types for it:
async function getCrypto ( query: string ): object { const url = new URL(... url.search = new URLSearchParams(... const headers = {... const response = await fetch( url.toString(), {headers} ); return await response.json(); };
Notice the colons : used to declare types for the query parameter as well as for the function itself. We will dive deeper into this shortly.
Declare the type of data we want to receive:
const query = { asset: "BTC", exchange: "Kraken", denominator: "USD", };
The top level closure will now just call our new function with our query data and log the results. It should look like this:
(async () => { const data = await getCrypto( query ); console.log(data) })()
There are some errors with our code so we want to fix them:
- The return type of an async function or method must be the global Promise<T> type.
- ‘await’ has no effect on the type of this expression.
- Argument of type ‘{ asset: string; exchange: string; denominator: string; }’ is not assignable to parameter of type ‘string’.
- Note how the URLSearchParams constructor might complain that it received an object and not a 2D array but it should still work.
Let’s take a look at the errors one by one.
Async return type
This is a pretty decent error message. It tells us exactly what it wants. Our function may eventually resolve to an object but the actual return type of an async coroutine is always a Promise.
So let’s fix this by correctly declaring the proper function return type:
async function getCrypto ( query: string ): Promise<object> { ...
Await has no effect
The reason we got this warning is that our getCrypto
function declared that it returned an object
, not a Promise
. So the type checker believed that the await
keyword was not needed.
But when we properly declare the return type as Promise<object>
then the type checker is perfectly happy with using await when calling it. After that, our warning should be gone.
Argument not assignable
The error points to the use of our query variable as an argument to the getCrypto function. The type checker assumes that the function signature contains the correct type which is string but our variable is an object.
Since we actually want the variable to be an object let’s fix the function signature:
async function getCrypto ( query: object ): Promise<object> { ...
URLSearchParams
The same thing is happening here as we saw in the last error: our query variable is an object but the URLSearchParams function expects one of:
- string,
- two-dimensional array of strings,
- Record,
- another URLSearchParams instance, or
- undefined.
Converting the query variable to a 2DArray will make the type checker happy; but, the code works if we leave it as an object. Since this detail is beyond the scope of this tutorial we’re going to leave it as is.
Connect to the Blockfacts.io API
Final Version
The final working version should look something like this:
async function getCrypto ( query: object ): Promise<object> { const url = new URL('https://crypto-asset-market-data-unified-apis-for-professionals.p.rapidapi.com/api/v1/exchanges/trades'); url.search = new URLSearchParams( query ).toString(); const headers = { "x-api-key": "[insert-your-api-key]", "x-api-secret": "[insert-your-api-secret]", "x-rapidapi-host": "crypto-asset-market-data-unified-apis-for-professionals.p.rapidapi.com", "x-rapidapi-key": "REPLACE_THIS_WITH_YOUR_KEY", }; const response = await fetch( url.toString(), {headers} ); return await response.json(); }; const query = { asset: "BTC", exchange: "Kraken", denominator: "USD", }; (async () => { const data = await getCrypto( query ); console.log(data) })()
Press the Run button and check the browser console. Did you get the expected Bitcoin data object? Mine looks like this:
{ "BTC-USD": [ { "exchange": "KRAKEN", "pair": "BTC-USD", "price": 9141.5, "tradeSize": 2.27959053, "denominatorSize": 20838.876829995002, "makerTaker": "buy", "tradeId": "", "exchangeTime": "1593547752.006385", "blockfactsTime": 1593547751822, "epochExchangeTime": 1593547752006 } ] }
Conclusion
I hope you enjoyed this tutorial and perhaps learned something about how to use an API with TypeScript. Next you can try making some calls from Node.js and React.js. If you want to experiment with other APIs be sure to check out the RapidAPI Marketplace. And of course, if you have any questions be sure to leave in the comments below.
Leave a Reply