One place for hosting & domains

      TypeScript

      How To Use Basic Types in TypeScript


      The author selected the COVID-19 Relief Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      TypeScript is an extension of the JavaScript language that uses JavaScript’s runtime with a compile-time type checker. This combination allows developers to use the full JavaScript ecosystem and language features, while also adding optional static type-checking, enum data types, classes, and interfaces. These features provide the developer with the flexibility of JavaScript’s dynamic nature, but also allow for a more reliable codebase, where type information can be used at compile-time to detect possible issues that could cause bugs or other unexpected behavior at runtime.

      The extra type information also provides better documentation of codebases and improved IntelliSense (code completion, parameters info, and similar content assist features) in text editors. Teammates can identify exactly what types are expected for any variable or function parameter, without having to go through the implementation itself.

      This tutorial will go through type declaration and all the basic types used in TypeScript. It will lead you through examples with different code samples, which you can follow along with in your own TypeScript environment or the TypeScript Playground, an online environment that allows you to write TypeScript directly in the browser.

      Prerequisites

      To follow this tutorial, you will need:

      • An environment in which you can execute TypeScript programs to follow along with the examples. To set this up on your local machine, you will need the following.
      • If you do not wish to create a TypeScript environment on your local machine, you can use the official TypeScript Playground to follow along.
      • You will need sufficient knowledge of JavaScript, especially ES6+ syntax, such as destructuring, rest operators, and imports/exports. If you need more information on these topics, reading our How To Code in JavaScript series is recommended.
      • This tutorial will reference aspects of text editors that support TypeScript and show in-line errors. This is not necessary to use TypeScript, but does take more advantage of TypeScript features. To gain the benefit of these, you can use a text editor like Visual Studio Code, which has full support for TypeScript out of the box. You can also try out these benefits in the TypeScript Playground.

      All examples shown in this tutorial were created using TypeScript version 4.2.2.

      Declaring Variable Types in TypeScript

      When writing code in JavaScript, which is a purely dynamic language, you can’t specify the data types of variables. You create the variables and assign them a value, but do not specify a type, as shown in the following:

      const language = {
        name: "JavaScript"
      };
      

      In this code block, language is an object that holds a string value for the property name. The value type for language and its properties is not explicitly set, and this could cause confusion later if future developers do not know what kind of value language references.

      TypeScript has as a main benefit a strict type system. A statically typed language is one where the type of the variables is known at compilation time. In this section, you will try out the syntax used to specify variable types with TypeScript.

      Types are extra information that you write directly in your code. The TypeScript compiler uses this extra information to enforce the correct use of the different values depending on their type.

      Imagine working with a dynamic language, such as JavaScript, and using a string variable as if it were a number. When you do not have strict unit testing, the possible bug is only going to appear during runtime. If using the type system available with TypeScript, the compiler would not compile the code, giving an error instead, like this:

      Output

      The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type. (2363)

      To declare a variable with a certain type in TypeScript, use the following syntax:

      declarationKeyword variableName: Type
      

      declarationKeyword would be something like let, var, or const. This would be followed by the variable name, a colon (:), and the type of that variable.

      Any code you write in TypeScript is, in some way, already using the type system, even if you are not specifying any types. Take this code as an example:

      let language="TypeScript";
      

      In TypeScript, this has the same meaning as the following:

      let language: string = 'TypeScript';
      

      In the first example, you did not set the type of the language variable to string, but TypeScript inferred the type because you assigned a string value when it was declared. In the second example, you are explicitly setting the type of the language variable to string.

      If you used const instead of let, it would be the following:

      const language="TypeScript";
      

      In this case, TypeScript would use the string literal TypeScript as the type of your variable, as if you typed it this way:

      const language: 'TypeScript' = 'TypeScript';
      

      TypeScript does this because, when using const, you are not going to assign a new value to the variable after the declaration, as doing this would raise an error.

      Note: If you are using an editor that supports TypeScript, hovering over the variables with your cursor will display the type information of each variable.

      If you explicitly set the type of a variable then use a different type as its value, the TypeScript Compiler (tsc) or your editor will show the error 2322. Try running the following:

      const myNumber: number="look! this is not a number :)";
      

      This will yield the following error:

      Output

      Type 'string' is not assignable to type 'number'. (2322)

      Now that you’ve tried out setting the type of a variable in TypeScript, the next section will show all the basic types supported by TypeScript.

      Basic Types Used in TypeScript

      TypeScript has multiple basic types that are used as building blocks when building more complex types. In the following sections, you are going to examine most of these types. Notice that most variables you are creating throughout this section could have their type omitted because TypeScript would be able to infer them, but you are being explicit about the types for learning purposes.

      string

      The type string is used for textual data types, like string literals or template strings.

      Try out the following code:

      const language: string = 'TypeScript';
      const message: string = `I'm programming in ${language}!`;
      

      In this code block, both language and message are assigned the string type. The template literal is still a string, even though it is determined dynamically.

      Since strings are common in JavaScript programming, this is probably one of the types you are going to use most.

      boolean

      The type boolean is used to represent true or false.

      Try out the code in the following block:

      const hasErrors: boolean = true;
      const isValid: boolean = false;
      

      Since hasErrors and isValid were declared as booleans, they can only be assigned the values true and false. Note that truthy and falsy values are not converted into their boolean equivalents and will throw an error if used with these variables.

      number

      The type number is used to represent integers and floats, as in the following:

      const pi: number = 3.14159;
      const year: number = 2021;
      

      This is another common type that is used often in JavaScript development, so this declaration will be common in TypeScript.

      bigint

      The type bigint is a type that can be used when targetting ES2020. It’s used to represent BigInt, which is a new datatype to store integers bigger than 2^53.

      Try the following code:

      const bigNumber: bigint = 9007199254740993n;
      

      Note: If this code throws an error, it is possible that TypeScript is not set up to target ES2020. This can be changed in your tsconfig.json file.

      If you are working with numbers bigger than 2^53 or with some Math libraries, bigint will be a common type declaration.

      symbol

      The symbol type is used to represent the Symbol primitive value. This will create a unique, unnamed value.

      Run the following code using the Symbol() constructor function:

      const mySymbol: symbol = Symbol('unique-symbol-value');
      

      The uniqueness of these values can be used to avoid reference collisions. For more on symbols in JavaScript, read the symbol article on Mozilla Developer Network (MDN).

      Arrays

      In TypeScript, arrays are typed based on the elements they are expected to have. There are two ways to type an array:

      • Appending [] to the expected type of the array elements. For example, if you want to type an array that holds multiple number values, you could do it like this:
      const primeNumbers: number[] = [2, 3, 5, 7, 11];
      

      If you assigned a string value to this array, TypeScript would give you an error.

      • Using the Array<T> Generic, where T is the expected type of the elements in that array. Using the previous example, it would become this:
      const primeNumbers: Array<number> = [2, 3, 5, 7, 11];
      

      Both ways are identical, so pick one and try using only that format to represent arrays. This will keep the codebase consistent, which is often more important than choosing one style over the other.

      One important aspect of using variables that hold arrays in TypeScript is that most of the time you will have to type them. Try the following code:

      const myArray = [];
      

      TypeScript is not able to infer the correct type expected by this array. Instead, it uses any[], which means an array of anything. This is not type-safe, and could cause confusion later in your code.

      To make your code more robust, it is recommended to be explicit about the types of the array. For example, this would make sure the array has number elements:

      const myArray: number[] = [];
      

      This way, if you try to push an invalid value to the array, TypeScript will yield an error. Try out the following code:

      const myArray: number[] = [];
      
      myArray.push('some-text');
      

      The TypeScript Compiler will show error 2345:

      Output

      Argument of type 'string' is not assignable to parameter of type 'number'. (2345)

      Tuples

      Tuples are arrays with a specific number of elements. One common use-case for this is storing 2D coordinates in the format [x, y]. If you are working with React and using Hooks, the result from most Hooks is also a tuple, like const [isValid, setIsValid] = React.useState(false).

      To type a tuple, as opposed to when typing an array, you wrap the type of the elements inside a [], separating them with commas. Imagine you are creating a literal array with the types of the elements:

      const position: [number, number] = [1, 2];
      

      If you try to pass less, or more, than the number of elements that the tuple expects, the TypeScript Compiler is going to show the error 2322.

      Take the following code, for example:

      const position: [number, number] = [1, 2, 3];
      

      This would yield the following:

      Output

      Type '[number, number, number]' is not assignable to type '[number, number]'. Source has 3 element(s) but target allows only 2. (2322)

      any

      In certain situations it may be too hard to specify the types of a value, such as if that value is coming from a third-party library or from code that was initially written without TypeScript. This can be especially common when migrating a JavaScript codebase to TypeScript in small steps. In these scenarios, it is possible to use a special type called any, which means any type. Using any means opting-out of type checking, and is the same as making the TypeScript Compiler ignore that value.

      Take the following code block:

      let thisCanBeAnything: any = 12345;
      
      thisCanBeAnything = "I can be anything - Look, I'm a string now";
      
      thisCanBeAnything = ["Now I'm an array - This is almost like pure JavaScript!"];
      

      None of these declarations will give an error in TypeScript, since the type was declared as any.

      Note: Most of the time, if you can, you should avoid using any. Using this loses one of the main benefits of TypeScript: having statically typed code.

      unknown

      The unknown type is like a type-safe counterpart of the any type. You can use unknown when you want to type something that you can not determine the value of, but still want to make sure that any code using that value is correctly checking the type before using it. This is useful for library authors with functions in their library that may accept a broad range of values from their users and do not want to type the value explicitly.

      For example, if you have a variable called code:

      let code: unknown;
      

      Then later in the program you can assign different values to that field, like 35 (number), or completely unrelated values, like arrays or even objects.

      Note: You are using let because you are going to assign a new value to that variable.

      Later in the same code, you could set code to a number:

      code = 35;
      

      But then later you could assign it to an array:

      code = [12345];
      

      You could even re-assign it to an object:

      code = {};
      

      If later in the code you want to compare that value against some other number, like:

      const isCodeGreaterThan100 = code > 100;
      

      The TypeScript compiler is going to display the error 2571:

      Output

      Object is of type 'unknown'. (2571)

      This happens because code needs to be a number type for this comparison, not an unknown type. When doing any operation with a value of type unknown, TypeScript needs to make sure that the type is the one it expects. One example of doing this is using the typeof operator that already exists in JavaScript. Examine the following code block:

      if (typeof code === 'number') {
        const isCodeGreaterThan100 = code > 60;
        // ...
      } else {
        throw new Error('Invalid value received as code');
      }
      

      In this example, you are checking if code is a number using the typeof operator. When you do that, TypeScript is going to coerce the type of your variable to number inside that if block, because at runtime the code inside the if block is only going to be executed if code is currently set to a number. Otherwise, you will throw a JavaScript error saying that the value passed is invalid.

      To understand the differences between the unknown and any types, you can think of unknown as “I do not know the type of that value” and any as “I do not care what type this value holds”.

      void

      You can use the void type to define the variable in question as holding no type at all. If you assign the result of a function that returns no value to a variable, that variable is going to have the type void.

      Take the following code:

      function doSomething() {};
      
      const resultOfVoidFunction: void = doSomething();
      

      You will rarely have to use the void type directly in TypeScript.

      null and undefined

      null and undefined values in TypeScript have their own unique types that are called by the same name:

      const someNullField: null = null;
      const someUndefinedField: undefined = undefined;
      

      These are especially useful when creating your own custom types, which will be covered later in this series.

      never

      The never type is the type of a value that will never exist. For example, imagine you create a numeric variable:

      const year: number = 2021;
      

      If you create an if block to run some code if year is not a number, it could be like the following:

      if (typeof year !== "number") {
        year;
      }
      

      The type of the variable year inside that if block is going to be never. This is because, since year is typed as number, the condition for this if block will never be met. You can think of the never type as an impossible type because that variable can’t have a value at this point.

      object

      The object type represents any type that is not a primitive type. This means that it is not one of the following types:

      • number
      • string
      • boolean
      • bigint
      • symbol
      • null
      • undefined

      The object type is commonly used to describe object literals because any object literal can be assigned to it:

      const programmingLanguage: object = {
        name: "TypeScript"
      };
      

      Note: There is a much better type than object that could be used in this case called Record. This has to do with creating custom types and is covered in a later tutorial in this series.

      Conclusion

      In this tutorial, you tried out the different basic types that are available in TypeScript. These types are going to be frequently used when working in a TypeScript codebase and are the main building blocks to create more complex, custom types.

      For more tutorials on TypeScript, check out our TypeScript Topic page.



      Source link

      How To Set Up a Gatsby Project with TypeScript


      The author selected the Diversity in Tech Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      TypeScript is a superset of JavaScript that adds optional static typing at build time, which cuts down on debugging runtime errors. It has grown into a powerful alternative to JavaScript over the years. At the same time, Gatsby has emerged as a useful front-end framework for creating static websites. TypeScript’s static-typing abilities go well with a static-site generator like Gatsby, and Gatsby has built-in support for coding in TypeScript.

      In this tutorial, you’re going to use Gatsby’s built-in capabilities to configure a Gatsby project for TypeScript. After this tutorial, you will have learned how to integrate TypeScript into your Gatsby project.

      Prerequisites

      • You will need to have both Node and npm installed in order to run a development environment and handle TypeScript- or Gatsby-related packages, respectively. This tutorial was tested with Node.js version 14.13.0 and npm version 6.14.8. To install on macOS or Ubuntu 18.04, follow the steps in How to Install Node.js and Create a Local Development Environment on macOS or the Installing Using a PPA section of How To Install Node.js on Ubuntu 18.04.
      • To create a new Gatsby project, you will need the Gatsby CLI command line tool installed on your computer. To set this up, follow Step 1 in How to Set Up Your First Gatsby Site. This step will also show you how to create a new Gatsby project with the gatsby new command.
      • You will need some familiarity with GraphQL queries and using GraphiQL to query for local image data. If you’d like a refresher on the query sandbox in GraphiQL, read How to Handle Images with GraphQL and the Gatsby Image API.
      • You will need sufficient knowledge of JavaScript, especially ES6+ syntax such as destructuring and imports/exports. You can find more information on these topics in Understanding Destructuring, Rest Parameters, and Spread Syntax in JavaScript and Understanding Modules and Import and Export Statements in JavaScript.
      • Since Gatsby is a React-based framework, you will be refactoring and creating components in this tutorial. You can learn more about this in How to Create Custom Components in React.
      • Additionally, you will need TypeScript installed on your machine. To do this, refer to the official TypeScript website. If you are using an editor besides Visual Studio Code, you may need to go through a few extra steps to make sure you have TypeScript performing type-checks at build time and showing any errors. For example, if you’re using Atom, you’ll need to install the atom-typescript package to be able to achieve a true TypeScript experience. If you would like to download TypeScript only for your project, do so after the Gatsby project folder has been set up.

      Step 1 — Creating a New Gatsby Site and Removing Boilerplate

      To get started, you’re going to create your Gatsby site and make sure that you can run a server and view the site. After that, you will remove some unused boilerplate files and code. This will set your project up for edits in later steps.

      Open your computer’s console/terminal and run the following command:

      • gatsby new gatsby-typescript-tutorial

      This will take a few seconds to run as it sets up the necessary boilerplate files and folders for the Gatsby site. After it is finished, cd into the project’s directory:

      • cd gatsby-typescript-tutorial

      To make sure the site’s development environment can start properly, run the following command:

      After a few seconds, you will receive the following message in the console:

      Output

      ... You can now view gatsby-starter-default in the browser. http://localhost:8000

      Usually, the default port is :8000, but you can change this by running gatsby develop -p another_number instead.

      Head over to your preferred browser and type http://localhost:8000 in the address bar to find the site. It will look like this:

      Gatsby Default Starter Site

      Next, you’ll remove all unnecessary files. This includes gatsby-node.js, gastby-browser.js, and gatsby-ssr.js:

      • rm gatsby-node.js
      • rm gastby-browser.js
      • rm gatsby-ssr.js

      Next, to finish setup, you’re going to remove some boilerplate code from your project’s index page. In your project’s root directory, head to the src directory, followed by pages and then open the index.js file.

      For this tutorial, you are only going to work with an <Image /> component, so you can delete code related to the <Link /> component, along with the h1 and p elements. Your file will then look like the following:

      gatsby-typescript-tutorial/src/pages/index.js

      import React from "react"
      
      import Layout from "../components/layout"
      import Image from "../components/image"
      import SEO from "../components/seo"
      
      const IndexPage = () => (
        <Layout>
          <SEO title="Home" />
          <div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
            <Image />
          </div>
        </Layout>
      )
      
      export default IndexPage
      

      Save and close the file.

      Now that you’ve created your project and completed some initial setup, you are ready to install the necessary plugins.

      Step 2 — Installing Dependencies

      In order to set up support for TypeScript in Gatsby, you’ll need some additional plugins and dependencies, which you will install in this step.

      The gatsby-plugin-typescript plugin already comes with a newly created Gatsby site. Unless you want to change any of its default options, you don’t have to add this plugin to your gatsby-config.js file explicitly. This Gatsby plugin makes writing .ts and .tsx files in TypeScript possible.

      Since your app can read TypeScript files, you will now change Gatsby’s JavaScript files to a TypeScript file extension. In particular, change header.js, image.js, layout.js, and seo.js in src/components and index.js in src/pages to header.tsx, image.tsx, layout.tsx, seo.tsx, and index.tsx:

      • mv src/components/header.js src/components/header.tsx
      • mv src/components/image.js src/components/image.tsx
      • mv src/components/layout.js src/components/layout.tsx
      • mv src/components/seo.js src/components/seo.tsx
      • mv src/pages/index.js src/pages/index.tsx

      You are using the mv command to rename the files to the second argument. .tsx is the file extension, since these files use JSX.

      There is one important caveat about the gatsby-plugin-typescript plugin, however: it doesn’t include type-checking at build time (a core function of TypeScript). If you’re using VS Code, this won’t be an issue because TypeScript is a supported language in Visual Studio. But if you’re using another editor, like Atom, you will need to do some extra configurations to achieve a full TypeScript development experience.

      Since Gatsby is a React-based framework, adding some additional React-related typing is also recommended. To add type-checking for types specific to React, run the following command:

      To add type-checking for types related to the React DOM, use this command:

      Now that you’ve become familiar with the plugin gatsby-plugin-typescript, you are ready to configure your Gatsby site for TypeScript in the next step.

      Step 3 — Configuring TypeScript for Gatsby with the tsconfig.json File

      In this step, you will create a tsconfig.json file. A tsconfig.json file has two primary purposes: establishing the root directory of the TypeScript project (include) and overriding the TypeScript compiler’s default configurations (compilerOptions). There are a couple of ways to create this file. If you have the tsc command line tool installed with npm, you could create a new tsconfig file with tsc --init. But the file is then populated with many default options and comments.

      Instead, create a new file at the root of your directory (gatsby-typescript-project/) and name it tsconfig.json.

      Next, create an object with two properties, compilerOptions and include, populated with the following code:

      gatsby-typescript-tutorial/tsconfig.json

       {
        "compilerOptions": {
          "module": "commonjs",
          "target": "es6",
          "jsx": "preserve",
          "lib": ["dom", "es2015", "es2017"],
          "strict": true,
          "noEmit": true,
          "isolatedModules": true,
          "esModuleInterop": true,
          "skipLibCheck": true,
          "noUnusedLocals": true,
          "noUnusedParameters": true,
          "removeComments": false
        },
        "include": ["./src/**/*"]
      }
      

      Note:
      This configuration is partially based on the gatsby-starter-typescript-plus starter.

      Save this file and close it when you are done.

      The include property points to an array of filenames or paths that the compiler knows to convert from TypeScript to JavaScript.

      Here is a brief explanation of each option used in compilerOptions:

      • module - Sets the module system for the project; commonjs is used by default.
      • target - Depending on what version of JavaScript you’re using, this option determines which features to downlevel and which to leave alone. This can be helpful if your project is deployed to older environments vs. newer environments.
      • jsx - Setting for how JSX is treated in .tsx files. The preserve option leaves the JSX unchanged.
      • lib - An array of specified type-definitions of different JS libraries/APIs (dom, es2015, etc.).
      • strict - When set to true, this enables TypeScript’s type-checking abilities at build-time.
      • noEmit - Since Gatsby already uses Babel to compile your code to readable JavaScript, you change this option to true to leave TypeScript out it.
      • isolatedModules - By choosing Babel as your compiler/transpiler, you are opting for compilation one file at a time, which may cause potential problems at runtime. Setting this option to true allows TypeScript to warn you if you are about to run into this problem.
      • esModuleIterop - Enabling this option allows your use of CommonJS (your set module) and ES modules (importing and exporting custom variables and functions) to better work together and allow namespace objects for all imports.
      • noUnusedLocals and noUnusedParamters - Enabling these two options disables the errors TypeScript would normally report if you were to create an unused local variable or parameter.
      • removeComments - Setting this to false (or not setting it at all) allows there to be comments present after any TypeScript files have been converted to JavaScript.

      You can learn more about these different options and many more by visiting TypeScript’s reference guide for tsconfig.

      Now that TypeScript is configured for Gatsby, you are going to complete your TypeScript integration by refactoring some of your boilerplate files in src/components and src/pages.

      Step 4 — Refactoring seo.tsx for TypeScript

      In this step, you’re going to add some TypeScript syntax to the seo.tsx file. This step goes in depth to explain some concepts of TypeScript; the next step will show how to refactor other boilerplate code in a more abbreviated manner.

      One feature of TypeScript is its flexibility with its syntax. If you don’t want to add typing to your variables explicitly, you don’t have to. Gatsby believes that adopting TypeScript in your workflow “can and should be incremental”, and so this step will concentrate on three core TypeScript concepts:

      • basic types
      • defining types and interfaces
      • working with build-time errors

      Basic Types in TypeScript

      TypeScript supports basic datatypes including: boolean, number, and string. The major syntactical difference with TypeScript, compared to JavaScript, is that variables can now be defined with an associated type.

      For example, the following code block shows how to assign the basic types with the highlighted code:

      let num: number;
      num = 0
      
      let str: string;
      str = "TypeScript & Gatsby"
      
      let typeScriptIsAwesome: boolean;
      typeScriptIsAwesome = true;
      

      In this code, num must be a number, str must be a string, and typeScriptIsAwesome must be a boolean.

      Now you will examine the defaultProps and propTypes declarations in the seo.tsx file, found in the src/components directory. Open the file in your editor and look for the following highlighted lines:

      gatsby-typescript-tutorial/src/components/seo.tsx

      ...
      import React from "react"
      import PropTypes from "prop-types"
      import { Helmet } from "react-helmet"
      import { useStaticQuery, graphql } from "gatsby"
      
      ...
            ].concat(meta)}
          />
        )
      }
      
      
      SEO.defaultProps = {
        lang: `en`,
        meta: [],
        description: ``,
      }
      
      SEO.propTypes = {
        description: PropTypes.string,
        lang: PropTypes.string,
        meta: PropTypes.arrayOf(PropTypes.object),
        title: PropTypes.string.isRequired,
      }
      
      export default SEO
      

      By default, a Gatsby site’s SEO component comes with a weak typing system using PropTypes. The defaultProps and propTypes are explicitly declared, using the imported PropsTypes class. For example, in the meta prop (or alias) of the propTypes object, its value is an array of objects, each of which is itself a prop of the PropTypes component. Some props are marked as required (isRequired) while others are not, implying they are optional.

      Since you are using TypeScript, you will be replacing this typing system. Go ahead and delete defaultProps and propTypes (along with the import statement for the PropTypes at the top of the file). Your file will look like the following:

      gatsby-typescript-tutorial/src/components/seo.tsx

       ...
      import React from "react"
      import { Helmet } from "react-helmet"
      import { useStaticQuery, graphql } from "gatsby"
      
      
      ...
            ].concat(meta)}
          />
        )
      }
      
      export default SEO
      

      Now that you’ve removed the default typing, you’ll write out the type aliases with TypeScript.

      Defining TypeScript Interfaces

      In TypeScript, an interface is used to define the “shape” of a custom type. These are used to represent the value type of complex pieces of data like React components and function parameters. In the seo.tsx file, you’re going to build an interface to replace the defaultProps and propTypes definitions that were deleted.

      Add the following highlighted lines:

      gatsby-typescript-tutorial/src/components/seo.ts

       ...
      import React from "react"
      import { Helmet } from "react-helmet"
      import { useStaticQuery, graphql } from "gatsby"
      
      interface SEOProps {
        description?: string,
        lang?: string,
        meta?: Array<{name: string, content: string}>,
        title: string
      }
      
      ...
      
      
      

      The interface SEOProps accomplishes what SEO.propTypes did by setting each of the properties associated data type as well as marking some as required with the ? character.

      Typing a Function

      Just like in JavaScript, functions play an important role in TypeScript applications. You can even type functions by specifying the datatype of the arguments passed into them. In the seo.tsx file, you will now work on the defined SEO function component. Under where the interface for SEOProps was defined, you’re going to explicitly declare the type of the SEO component’s function arguments, along with a return type of SEOProps right after:

      Add the following highlighted code:

      gatsby-typescript-tutorial/src/components/seo.ts

      ...
      interface SEOProps {
        description?: string,
        lang?: string,
        meta?: Array<{name: string, content: string}>,
        title: string
      }
      
      function SEO({ description='', lang='en', meta=[], title }: SEOProps) {
        ...
      }
      

      Here you set defaults for the SEO function arguments so that they adhere to the interface, and added the interface with : SEOProps. Remember that you at least have to include the title in the list of arguments passed to the SEO component because it was defined as a required property in the SEOProps interface you defined earlier.

      Lastly, you can revise the metaDescription and defaultTitle constant declarations by setting their type, which is string in this case:

      gatsby-typescript-tutorial/src/components/seo.tsx

       ...
      function SEO({ description='', lang='en', meta=[], title }: SEOProps) {
        const { site } = useStaticQuery(
          graphql`
            query {
              site {
                siteMetadata {
                  title
                  description
                  author
                }
              }
            }
          `
        )
      
        const metaDescription: string = description || site.siteMetadata.description
        const defaultTitle: string = site.siteMetadata?.title
      ...
      

      Another type in TypeScript is the any type. For situations where you’re dealing with a variable whose type is unclear or difficult to define, use any as a last resort to avoid any build-time errors.

      An example of using the any type is when dealing with data fetched from a third-party, like an API request or a GraphQL query. In the seo.tsx file, where the destructured site property is defined with a GraphQL static query, set its type to any:

      gatsby-typescript-tutorial/src/components/seo.tsx

      ...
      interface SEOProps {
        description?: string,
        lang?: string,
        meta?: Array<{name: string, content: string}>,
        title: string
      }
      
      function SEO({ description='', lang='en', meta=[], title }: Props) {
        const { site }: any = useStaticQuery(
          graphql`
            query {
              site {
                siteMetadata {
                  title
                  description
                  author
                }
              }
            }
          `
        )
        ...
      }
      

      Save and exit the file.

      It’s important to always keep the defined values consistent with their type. Otherwise, you will see build-time errors appear via the TypeScript compiler.

      Build-Time Errors

      It will be helpful to become accustomed to the errors TypeScript will catch and report at build-time. The idea is that TypeScript catches these errors, mostly type-related, at build-time, and this cuts down on the amount of debugging in the long run (in compile-time).

      One example of a build-time error occurring is when you declare a variable of one type but assign it a value that is of another type. If you were to change the value of one of the keyword arguments passed to the SEO component to one of a different type, the TypeScript compiler will detect the inconsistency and report the error. The following is an image of what this looks like in VSCode:

      A build-time error in VSCode when the description variable is set to a number.

      The error says Type 'number' is not assignable to type 'string'. This is because, when you set up your interface, you said the description property would be of type string. The value 0 is of type number. If you change the value of description back into a “string”, the error message will go away.

      Step 5 — Refactoring the Rest of the Boilerplate

      Lastly, you will refactor the remaining boilerplate files with TypeScript: layout.tsx, image.tsx, and header.tsx. Like seo.tsx, these component files are located in the src/components directory.

      Open src/components/layout.tsx. Towards the bottom, is the defined Layout.propTypes. Delete the following highlighted lines:

      gatsby-typescript-tutorial/src/components/layout.tsx

       import React from "react"
      import PropTypes from "prop-types"
      import { useStaticQuery, graphql } from "gatsby"
      ...
      
      Layout.propTypes = {
        children: PropTypes.node.isRequired,
      }
      
      export default Layout
      

      The children prop shows that its value is of type node per the PropTypes class. Plus, it’s a required prop. Since the children in the layout could be anything from simple text to React child components, use ReactNode as the associated type by importing near the top and adding it to the interface:

      Add the following highlighted lines:

      gatsby-typescript-tutorial/src/components/layout.tsx

      ...
      import React, { ReactNode } from "react"
      import { useStaticQuery, graphql } from "gatsby"
      
      import Header from "./header"
      import "./layout.css"
      
      interface LayoutProps {
        children: ReactNode
      }
      
      const Layout = ({ children }: LayoutProps) => {
        ...
      

      Next, add a type to the data variable that stores a GraphQL query that fetches site title data. Since this query object is coming from a third-party entity like GraphQL, give data an any type. Lastly, add the string type to the siteTitle variable that works with that data:

      gatsby-typescript-tutorial/src/components/layout.tsx

       ...
      const Layout = ({ children }: LayoutProps) => {
        const data: any = useStaticQuery(graphql`
        query MyQuery {
          site {
            siteMetadata {
              title
            }
          }
        }
      `)
      
      const siteTitle: string = data.site.siteMetadata?.title || `Title`
      
        return (
          <>
            <Header siteTitle={siteTitle} />
            <div
      ...
      

      Save and close the file.

      Next, open the src/components/image.tsx file.

      Here you are dealing with a similar situation as layout.tsx. There is a data variable that stores a GraphQL query that could have an any type. The image fluid data that is passed into the fluid attribute of the <Img /> component could be separated from the return statement into its own variable. It’s also a complex variable like data, so give this an any type as well:

      gatsby-typescript-tutorial/src/components/image.tsx

      ...
      const Image = () => {
        const data: any = useStaticQuery(graphql`
          query {
            placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
              childImageSharp {
                fluid(maxWidth: 300) {
                  ...GatsbyImageSharpFluid
                }
              }
            }
          }
        `)
      
        if (!data?.placeholderImage?.childImageSharp?.fluid) {
          return <div>Picture not found</div>
        }
      
        const imageFluid: any = data.placeholderImage.childImageSharp.fluid
      
        return <Img fluid={imageFluid} />
      }
      
      export default Image
      

      Save and close the file.

      Now open the src/components/header.tsx file. This file also comes with predefined prop types, using the PropTypes class. Like seo.tsx, image.tsx, and layout.tsx, replace Header.defaultProps and Header.propTypes with an interface using the same prop names:

      gatsby-typescript-tutorial/src/components/header.tsx

      import { Link } from "gatsby"
      import React from "react"
      
      interface HeaderProps {
        siteTitle: string
      }
      
      const Header = ({ siteTitle }: HeaderProps) => (
        <header
          style={{
            background: `rebeccapurple`,
            marginBottom: `1.45rem`,
          }}
        >
          <div
            style={{
              margin: `0 auto`,
              maxWidth: 960,
              padding: `1.45rem 1.0875rem`,
            }}
          >
            <h1 style={{ margin: 0 }}>
              <Link
                to="/"
                style={{
                  color: `white`,
                  textDecoration: `none`,
                }}
              >
                {siteTitle}
              </Link>
            </h1>
          </div>
        </header>
      )
      
      export default Header
      

      Save and close the file.

      With your files refactored for TypeScript, you can now restart the server to make sure everything is working. Run the following command:

      When you navigate to localhost:8000, your browser will render the following:

      Gatsby Default Development page

      Conclusion

      TypeScript’s static-typing capabilities go a long way in keeping debugging at a minimum. It’s also a great language for Gatsby sites since it’s supported by default. Gatsby itself is a useful front-end tool for creating static-sites, such as landing pages.

      You now have two popular tools at your disposal. To learn more about TypeScript and all you can do with it, head over to the official TypeScript handbook.



      Source link

      Cara Menyiapkan Proyek Node dengan Typescript


      Pengantar

      Node adalah lingkungan run-time yang memungkinkan penulisan JavaScript di pihak server. Ini telah banyak digunakan sejak dirilis tahun 2011. Menulis JavaScript di pihak server dapat menjadi hal yang menantang seiring berkembangnya basis kode karena sifat bahasa JavaScript; dinamis dan bertipe lemah.

      Para pengembang yang memilih JavaScript dari bahasa lain sering mengeluhkan kekurangan tipe statis kuat, di sinilah TypeScript hadir menjembatani kesenjangan itu.

      TypeScript adalah super-set bertipe (opsional) dari JavaScript yang dapat membantu membangun dan mengelola proyek JavaScript berskala besar. Ini dapat dianggap sebagai JavaScript dengan fitur tambahan, seperti tipe statis kuat, kompilasi, dan pemrograman berorientasi objek.

      Catatan: TypeScript secara teknis adalah super-set JavaScript, yang berarti semua kode JavaScript adalah kode TypeScript yang valid.

      Berikut ini beberapa manfaat menggunakan TypeScript:

      1. Tipe statis opsional.
      2. Tipe interferensi.
      3. Kemampuan untuk menggunakan Antarmuka.

      Dalam tutorial ini, Anda akan menyiapkan proyek Node dengan TypeScript. Anda akan membangun aplikasi Express menggunakan TypeScript dan menerjemahkannya menjadi kode JavaScript yang rapi dan andal.

      Prasyarat

      Sebelum memulai panduan ini, Node.js sudah harus terinstal di mesin Anda. Anda dapat melakukannya dengan mengikuti panduan Cara Menginstal Node.js dan Membuat Lingkungan Pengembangan Lokal bagi sistem operasi Anda.

      Langkah 1 — Inisialisasi Proyek npm

      Untuk memulai, buat folder baru bernama node_project dan pindah ke direktori itu.

      • mkdir node_project
      • cd node_project

      Selanjutnya, inisialisasi sebagai proyek npm:

      Setelah menjalankan init npm, Anda perlu memberikan informasi tentang proyek Anda kepada npm. Jika Anda lebih suka membiarkan npm mengasumsikan asali yang wajar, Anda dapat menambahkan bendera y untuk melewatkan prompt informasi tambahan:

      Karena kini ruang proyek sudah disiapkan, Anda siap untuk melanjutkan ke instalasi dependensi yang diperlukan.

      Langkah 2 — Menginstal Dependensi

      Dengan proyek npm kosong yang telah diinisialisasi, langkah selanjutnya adalah menginstal dependensi yang diperlukan untuk menjalankan TypeScript.

      Jalankan perintah berikut dari direktori proyek Anda untuk menginstal dependensi:

      Bendera -D adalah pintasan untuk: --save-dev. Anda dapat mempelajari lebih lanjut tentang bendera ini dalam dokumentasi npmjs.

      Sekarang, saatnya menginstal kerangka kerja Express:

      Perintah kedua menginstal beberapa tipe Express untuk dukungan TypeScript. Tipe dalam TypeScript adalah berkas, biasanya dengan ekstensi .d.ts. Berkas digunakan untuk memberikan informasi tentang API kepada tipe, dalam hal ini adalah kerangka kerja Express.

      Paket ini diperlukan karena TypeScript dan Express adalah paket independen. Tanpa paket @types/express, TypeScript tidak dapat mengetahui tipe kelas Express.

      Langkah 3 — Mengonfigurasi TypeScript

      Di bagian ini, Anda akan menyiapkan TypeScript dan mengonfigurasi proses lint untuk TypeScript. TypeScript menggunakan berkas bernama tsconfig.json untuk mengonfigurasi opsi pengompilasi proyek. Buat berkas tsconfig.json di root direktori proyek dan tempelkan dalam cuplikan kode berikut:

      tsconfig.json

      {
        "compilerOptions": {
          "module": "commonjs",
          "esModuleInterop": true,
          "target": "es6",
          "moduleResolution": "node",
          "sourceMap": true,
          "outDir": "dist"
        },
        "lib": ["es2015"]
      }
      

      Mari kita tinjau beberapa hal pokok dalam cuplikan JSON di atas:

      • module: Menentukan metode pembuatan kode modul. Node menggunakan commonjs.
      • target: Menentukan tingkat bahasa keluaran.
      • moduleResolution: Ini membantu pengompilasi mengetahui apa yang dirujuk oleh impor. Nilai node menirukan mekanisme resolusi modul Node.
      • outDir: Ini adalah lokasi untuk keluaran berkas .js setelah penerjemahan. Dalam tutorial ini, Anda akan menyimpannya sebagai dist.

      Alternatif untuk membuat dan mengisi berkas tsconfig.json adalah dengan menjalankan perintah berikut:

      Perintah ini akan menghasilkan berkas tsconfig.json yang telah diberi komentar dengan baik.

      Untuk mempelajari lebih lanjut berbagai opsi nilai kunci yang tersedia, dokumentasi TypeScript resmi memberikan penjelasan tentang setiap opsi.

      Sekarang Anda dapat mengonfigurasi proses lint TypeScript untuk proyek. Dalam terminal yang sedang berjalan di root direktori proyek Anda, tempat tutorial ini dibuat sebagai node_project, jalankan perintah berikut untuk menghasilkan berkas tslint.json:

      • ./node_modules/.bin/tslint --init

      Buka berkas tslint.json yang baru dihasilkan dan tambahkan aturan no-console yang sesuai:

      tslint.json

      {
        "defaultSeverity": "error",
        "extends": ["tslint:recommended"],
        "jsRules": {},
        "rules": {
          "no-console": false
        },
        "rulesDirectory": []
      }
      

      Secara asali, linter di TypeScript mencegah penggunaan awakutu dengan pernyataan console, sehingga perlu secara eksplisit memberi tahu linter untuk mencabut aturan no-console asali.

      Langkah 4 — Memperbarui Berkas package.json

      Pada titik ini dalam tutorial, Anda dapat menjalankan fungsi dalam terminal satu per satu, atau membuat npm script untuk menjalankannya.

      Dalam langkah ini, Anda akan membuat skrip start yang akan mengompilasi dan menerjemahkan kode TypeScript, kemudian menjalankan app.js yang dihasilkan.

      Buka berkas package.json dan perbarui sebagaimana mestinya:

      package.json

      {
        "name": "node-with-ts",
        "version": "1.0.0",
        "description": "",
        "main": "dist/app.js",
        "scripts": {
          "start": "tsc && node dist/app.js",
          "test": "echo "Error: no test specified" && exit 1"
        },
        "author": "",
        "license": "ISC",
        "devDependencies": {
          "@types/express": "^4.16.1",
          "tslint": "^5.12.1",
          "typescript": "^3.3.3"
        },
        "dependencies": {
          "express": "^4.16.4"
        }
      }
      

      Dalam cuplikan di atas, Anda memperbarui jalur main dan menambahkan perintah start ke bagian skrip. Bila memperhatikan perintah start, Anda akan melihat bahwa perintah tsc pertama adalah berjalan, kemudian perintah node. Ini akan mengompilasi kemudian menjalankan keluaran yang dihasilkan dengan node.

      Perintah tsc memberi tahu TypeScript untuk mengompilasi aplikasi dan menempatkan keluaran .js yang dihasilkan dalam direktori outDir yang ditentukan karena telah diatur dalam berkas tsconfig.json.

      Langkah 5 — Membuat dan Menjalankan Server Express Dasar

      Karena TypeScript dan linter telah dikonfigurasi, saatnya membangun Server Express Node.

      Pertama-tama, buat folder src di root direktori proyek Anda:

      Kemudian, buat berkas bernama app.ts di dalamnya:

      Sehingga struktur folder akan terlihat seperti ini:

      ├── node_modules/
      ├── src/
        ├── app.ts
      ├── package-lock.json
      ├── package.json
      ├── tsconfig.json
      ├── tslint.json
      

      Buka berkas app.ts dengan editor teks pilihan Anda dan tempelkan dalam cuplikan kode berikut:

      src/app.ts

      import express from 'express';
      
      const app = express();
      const port = 3000;
      app.get('/', (req, res) => {
        res.send('The sedulous hyena ate the antelope!');
      });
      app.listen(port, err => {
        if (err) {
          return console.error(err);
        }
        return console.log(`server is listening on ${port}`);
      });
      

      Kode di atas membuat Server Node yang mendengarkan permintaan di porta 3000. Jalankan aplikasi menggunakan perintah berikut:

      Jika berhasil dijalankan, pesan akan dicatat ke terminal:

      Output

      • server is listening on 3000

      Sekarang, Anda dapat mengunjungi http://localhost:3000 di peramban Anda dan seharusnya melihat pesan:

      Output

      • The sedulous hyena ate the antelope!

      Jendela peramban berisi pesan: The sedulous hyena ate the antelope!

      Buka berkas dist/app.js dan Anda akan menemukan versi kode TypeScript yang telah diterjemahkan:

      dist/app.js

      "use strict";
      
      var __importDefault = (this && this.__importDefault) || function (mod) {
          return (mod && mod.__esModule) ? mod : { "default": mod };
      };
      Object.defineProperty(exports, "__esModule", { value: true });
      const express_1 = __importDefault(require("express"));
      const app = express_1.default();
      const port = 3000;
      app.get('/', (req, res) => {
          res.send('The sedulous hyena ate the antelope!');
      });
      app.listen(port, err => {
          if (err) {
              return console.error(err);
          }
          return console.log(`server is listening on ${port}`);
      });
      
      //# sourceMappingURL=app.js.map
      

      Saat ini, Anda berhasil menyiapkan proyek Node menggunakan TypeScript.

      Kesimpulan

      Dalam tutorial ini, Anda telah mempelajari alasan TypeScript berguna untuk penulisan kode JavaScript yang andal. Anda juga telah mempelajari beberapa manfaat menggunakan TypeScript.

      Terakhir, Anda telah menyiapkan proyek Node dengan kerangka kerja Express, kemudian mengompilasi dan menjalankan proyek dengan TypeScript.



      Source link