The source code for this blog is available on GitHub.
Note
Top

DOM in TypeScript: A Comprehensive Guide

Cover Image for DOM in TypeScript: A Comprehensive Guide
Han Chen
Han Chen

DOM

I am not really into the typescript stuff

Button and Div differences

<div
  onClick={handleBack}
  className="ml-4 cursor-pointer text-blue-600 dark:text-blue-500 hover:underline"
>
  Back to sign in
</div>
<button
  onClick={handleBack}
  className="ml-4 cursor-pointer text-blue-600 dark:text-blue-500 hover:underline"
>
  Back to sign in
</button>

The code block provided in the "Wrong" section is using a div element, which is not the appropriate HTML element to use for a clickable button. A div element is a generic container for flow content and does not have any semantic meaning. On the other hand, the button element is a button-specific element that indicates an interactive control for triggering actions.

Therefore, the code block in the "Right" section is the correct usage of an HTML button element with the onClick event handler for triggering the handleBack function. This code block is semantically correct and will result in a more accessible and usable interface for users.

ReactNode

The type of the label prop in the code snippet you provided is React.ReactNode. It's a type that represents any valid React element. In this case, it's an empty <></> component, which is equivalent to a fragment in React.

// How to use checkbox.tsx
<Checkbox
  round
  onClick={() => handlePrimary(address.id)}
  checked={primaryAddressId === address.id}
  wrapperClass="mt-0 mb-6"
  label={<></>}
/>

// checkbox.tsx
import React from "react";
import classname from "classnames";
import Checkmark from "./icons/Checkmark";

interface Props {
  onClick: (e: any) => void;
  checked: boolean;
  label?: string | React.FC<Props> | React.ComponentClass<Props> | React.ReactNode;
  children?: any;
  round?: boolean;
  wrapperClass?: string;
  labelClass?: string;
}

const Checkbox: React.FC<Props> = ({
  onClick,
  checked,
  label,
  children,
  round = false,
  wrapperClass,
  labelClass,
}) => (
  <div className={classname("flex", wrapperClass)}>
    ...
    <div className={labelClass}>{label || children || "Label"}</div>
  </div>
);

export default Checkbox;

exclamation mark with google api autocomplete input field

To add type to the autoComplete variable, you can simply declare the variable with a specific type like this:

let autoComplete: google.maps.places.Autocomplete;

This will explicitly define the type of autoComplete as an instance of the google.maps.places.Autocomplete class.

Here's the updated code with the type added:

const autoCompleteRef = useRef<HTMLInputElement>(null);
const [addressError, setAddressError] = useRecoilState(addressErrorState);
const [manualEdit, setManualEdit] = useState<boolean>(false); // manually edit address

useEffect(() => {
  // Torbram Rd, Brampton, ON, Canada
  let autoComplete: google.maps.places.Autocomplete = new window.google.maps.places.Autocomplete(
    autoCompleteRef.current!,
    googleGeoOptions
  );
  
  // Add event listeners to handle place selection
  autoComplete.addListener("place_changed", handlePlaceSelect);
}, []);

Note that we also added the HTMLInputElement type to the useRef hook, as autoCompleteRef is a reference to an input element.

To add type to autoCompleteRef.current, you can specify the type of the referenced element. In this case, since autoCompleteRef is referencing an input element, you can use the HTMLInputElement type. Here's the updated code:

const autoCompleteRef = useRef<HTMLInputElement>(null);
const [addressError, setAddressError] = useRecoilState(addressErrorState);
const [manualEdit, setManualEdit] = useState<boolean>(false); // manually edit address

useEffect(() => {
  // Torbram Rd, Brampton, ON, Canada
  let autoComplete: google.maps.places.Autocomplete = new window.google.maps.places.Autocomplete(
    autoCompleteRef.current!,
    googleGeoOptions
  );
  
  // Add event listeners to handle place selection
  autoComplete.addListener("place_changed", handlePlaceSelect);
}, []);

Note that we added HTMLInputElement to specify that autoCompleteRef.current is a reference to an input element. The ! is used to indicate that we know for sure that autoCompleteRef.current will not be null, as it is checked in the useEffect hook. If there's a chance that autoCompleteRef.current could be null, you should use a conditional check to avoid runtime errors.

the ! symbol is a TypeScript syntax called the non-null assertion operator.

It is used to tell the TypeScript compiler that a value will not be null or undefined at runtime, even if the type system indicates that it might be.

For example, if you have a variable of type string | undefined, TypeScript will not allow you to call any methods or access any properties of the variable, because it might be undefined at runtime. However, if you know for certain that the variable will not be undefined when you access it, you can use the non-null assertion operator to tell TypeScript to allow it:

const myString: string | undefined = "hello";
const myLength: number = myString!.length;

In this example, the ! operator is used to tell TypeScript that myString will not be undefined when length is accessed. If you try to access length without the !, TypeScript will throw an error.

It's important to use the non-null assertion operator with caution, as it can lead to runtime errors if you make incorrect assumptions about the value of a variable. It's always better to use null-checking techniques like optional chaining and conditional checks whenever possible.

© 2024 WOOTHINK. All Rights Reserved.
Site MapTerms and ConditionsPrivacy PolicyCookie Policy