JSX Flashcards
What is JSX?
JSX is an embeddable XML-like syntax. It is meant to be transformed into valid JavaScript.
TypeScript supports embedding, type checking, and compiling JSX directly to JavaScript. JSX is used widely in frameworks like React and it allows HTML/XML-like syntax to be used in JavaScript code.
“Documentation - JSX” (typescriptlang.org). Retrieved June 28, 2023.
What are the necessary steps to use JSX in TypeScript?
To use JSX in TypeScript, you must:
- Name your files with a
.tsx
extension - Enable the
jsx
compiler option in your TypeScript configuration.
“JSX Basic usage” (typescriptlang.org). Retrieved June 28, 2023.
What are the different JSX modes in TypeScript and what are their outputs?
TypeScript supports several JSX modes:
-
preserve
: Keeps the JSX as part of the output for further transformation. The output file will have a.jsx
extension. -
react
: EmitsReact.createElement
. The output doesn’t need further JSX transformation and will have a.js
extension. -
react-native
: Equivalent to preserve, but the output will have a.js
extension. -
react-jsx
: Transforms JSX to'_jsx("div", {}, void 0);'
. The output file has a.js
extension. -
react-jsxdev
: Transforms JSX to'_jsxDEV("div", {}, void 0, false, {...}, this);'
. The output file has a.js
extension.
“JSX Basic usage” (typescriptlang.org). Retrieved June 28, 2023.
How do you specify the JSX mode and JSX factory function in TypeScript?
The JSX mode can be specified using the 'jsx'
command line flag or the corresponding 'jsx'
compiler option in your tsconfig.json file.
To specify the JSX factory function (which defaults to React.createElement
when targeting react
JSX emit), you can use the 'jsxFactory'
compiler option in your TypeScript configuration.
“JSX Basic usage” (typescriptlang.org). Retrieved June 28, 2023.
Why does TypeScript disallow angle bracket type assertions in .tsx
files?
TypeScript disallows angle bracket type assertions in .tsx
files because TypeScript also uses angle brackets for type assertions, which would introduce certain parsing difficulties when combined with JSX’s syntax.
“JSX, The as operator” (typescriptlang.org). Retrieved June 28, 2023.
What is the alternative to angle bracket type assertions in .tsx
files?
The as
operator.
For instance,
const foo = bar as foo;
asserts that the variable bar
is of type foo
. The as
operator is identical in behavior to the angle-bracket type assertion style.
“JSX, The as operator” (typescriptlang.org). Retrieved June 28, 2023.
What is the difference between intrinsic elements and value-based elements in JSX type checking?
In JSX type checking, intrinsic elements refer to elements that are intrinsic to the environment, such as a div
or span
in a DOM environment. On the other hand, value-based elements refer to custom components created by the user.
Intrinsic elements are emitted as strings in React (React.createElement("div")
), while value-based elements (components created by the user) are not (React.createElement(MyComponent)
). Furthermore, the types of the attributes being passed in the JSX element are looked up differently for each. Attributes for intrinsic elements should be known intrinsically, whereas components may want to specify their own set of attributes.
In TypeScript and React, an intrinsic element always begins with a lowercase letter, while a value-based element always begins with an uppercase letter.
“JSX Type Checking” Retrieved July 3, 2023.
How does TypeScript distinguish between intrinsic and value-based elements in JSX?
TypeScript uses the same convention that React does for distinguishing between intrinsic and value-based elements in JSX. An intrinsic element always begins with a lowercase letter, while a value-based element (a custom component) always begins with an uppercase letter.
“JSX Type Checking” Retrieved July 3, 2023.
What are intrinsic elements in TypeScript JSX?
Intrinsic elements in TypeScript JSX refer to elements that are intrinsic to the environment, such as a div
or span
in a DOM environment. They are looked up on the special interface JSX.IntrinsicElements
.
“JSX Intrinsic elements” (typescriptlang.org). Retrieved July 3, 2023.
How are intrinsic elements type checked in TypeScript JSX?
Intrinsic elements in TypeScript JSX are type checked using the JSX.IntrinsicElements
interface. If this interface is present, the name of the intrinsic element is looked up as a property on the JSX.IntrinsicElements
interface. For example, if the interface declares a foo
property, <foo />
will pass type checking but <bar />
will fail as it’s not declared in the interface.
For example:
declare namespace JSX { interface IntrinsicElements { foo: any; } } <foo />; // ok <bar />; // error
“JSX Intrinsic elements” (typescriptlang.org). Retrieved July 3, 2023.
What happens if the JSX.IntrinsicElements
interface is not specified in TypeScript JSX?
If the JSX.IntrinsicElements
interface is not specified in TypeScript JSX, then intrinsic elements will not be type checked. This means any intrinsic element name can be used without causing an error.
“JSX Intrinsic elements” (typescriptlang.org). Retrieved July 3, 2023.
How can a catch-all string indexer be used in JSX.IntrinsicElements
interface in TypeScript JSX?
A catch-all string indexer can be used on the JSX.IntrinsicElements
interface to accept any string as an element name. This is done as follows:
declare namespace JSX { interface IntrinsicElements { [elemName: string]: any; } }
“JSX Intrinsic elements” (typescriptlang.org). Retrieved July 3, 2023.
What are value-based elements in TypeScript JSX?
Value-based elements in TypeScript JSX refer to custom components that you’ve created. These elements are looked up by identifiers that are in scope.
For example, if you import and use MyComponent
from "./myComponent"
, <MyComponent />
will be ok. But using an undefined component like <SomeOtherComponent />
will result in an error.
“JSX Value-based elements” (typescriptlang.org). Retrieved July 3, 2023.
How does TypeScript resolve value-based elements in JSX?
In TypeScript, there are two ways to define a value-based element:
- Function Component (FC) and
- Class Component.
In JSX expressions, Function Component and Class Component are indistinguishable from each other. Thus, TypeScript first tries to resolve the expression as a Function Component using overload resolution. If that process succeeds, TypeScript finishes resolving the expression to its declaration.
“JSX Value-based elements” (typescriptlang.org). Retrieved July 3, 2023.
What happens if TypeScript fails to resolve a value-based element as a Function Component?
If TypeScript fails to resolve a value-based element as a Function Component, it then tries to resolve it as a Class Component. If that also fails, TypeScript will report an error.
“JSX Value-based elements” (typescriptlang.org). Retrieved July 3, 2023.
What is a Function Component in TypeScript?
In TypeScript, a Function Component is a JavaScript function where its first argument is a props object, and its return type must be assignable to JSX.Element
.
“Function Component” (typescriptlang.org). Retrieved July 3, 2023.
How do you define props for a Function Component in TypeScript?
You can define props for a Function Component by creating an interface that describes the shape of the props object.
For example:
interface FooProp { name: string; X: number; Y: number; } function ComponentFoo(prop: FooProp) { return <AnotherComponent name={prop.name} />; }
“Function Component” (typescriptlang.org). Retrieved July 3, 2023.
Can you use function overloads with Function Components in TypeScript? If so, provide an example.
Yes, you can use function overloads with Function Components in TypeScript.
For example:
interface ClickableProps { children: JSX.Element[] | JSX.Element; } interface HomeProps extends ClickableProps { home: JSX.Element; } interface SideProps extends ClickableProps { side: JSX.Element | string; } function MainButton(prop: HomeProps): JSX.Element; function MainButton(prop: SideProps): JSX.Element; function MainButton(prop: ClickableProps): JSX.Element { // ... }
“Function Component” (typescriptlang.org). Retrieved July 3, 2023.
What are the element class type and element instance type in TypeScript when dealing with JSX?
- The element class type is the type of the component, such as a
class
orfunction
, used in a JSX expression. - The element instance type is determined by the return types of the class type’s construct or call signatures.
“Class Component” (typescriptlang.org). Retrieved July 4, 2023.
Provide an example of determining element class type and instance type for both a class component and a factory function in TypeScript.
class MyComponent { render() {} } // use a construct signature const myComponent = new MyComponent(); // element class type => MyComponent // element instance type => { render: () => void } function MyFactoryFunction() { return { render: () => {}, }; } // use a call signature const myComponent = MyFactoryFunction(); // element class type => MyFactoryFunction // element instance type => { render: () => void }
“Class Component” (typescriptlang.org). Retrieved July 4, 2023.
What conditions must the element instance type meet in TypeScript and JSX? What happens if it doesn’t meet these conditions?
The element instance type must be assignable to JSX.ElementClass
or it will result in an error. By default JSX.ElementClass
is {}, but it can be augmented to limit the use of JSX to only those types that conform to the proper interface.
“Class Component” (typescriptlang.org). Retrieved July 4, 2023.
Provide an example of a valid and invalid class component and factory function according to JSX.ElementClass
.
declare namespace JSX { interface ElementClass { render: any; } } class MyComponent { render() {} } function MyFactoryFunction() { return { render: () => {} }; } <MyComponent />; // ok <MyFactoryFunction />; // ok class NotAValidComponent {} function NotAValidFactoryFunction() { return {}; } <NotAValidComponent />; // error <NotAValidFactoryFunction />; // error
“Class Component” (typescriptlang.org). Retrieved July 4, 2023.
How does attribute type checking work for intrinsic elements in JSX with TypeScript?
For intrinsic elements, the attribute type is determined by the type of the property on JSX.IntrinsicElements
. For example:
declare namespace JSX { interface IntrinsicElements { foo: { requiredProp: string; optionalProp?: number }; } } <foo requiredProp="bar" />; // ok <foo requiredProp="bar" optionalProp={0} />; // ok <foo />; // error, requiredProp is missing <foo requiredProp={0} />; // error, requiredProp should be a string <foo requiredProp="bar" unknownProp />; // error, unknownProp does not exist <foo requiredProp="bar" some-unknown-prop />; // ok, because 'some-unknown-prop' is not a valid identifier
“JSX Attribute type checking” (typescriptlang.org). Retrieved July 5, 2023.
How does attribute type checking work for value-based elements in JSX with TypeScript?
For value-based elements, the attribute type is determined by the type of a property on the element instance type. Which property to use is determined by JSX.ElementAttributesProperty
. It should be declared with a single property, and the name of that property is then used.
For example:
declare namespace JSX { interface ElementAttributesProperty { props; // specify the property name to use } } class MyComponent { // specify the property on the element instance type props: { foo?: string; }; } // element attributes type for 'MyComponent' is '{foo?: string}' <MyComponent foo="bar" />;
“JSX Attribute type checking” (typescriptlang.org). Retrieved July 5, 2023.
Hello, {user.name}
; ``` In this case, `user.name` is a JavaScript expression embedded in JSX. ## Footnote ["Embedding Expressions" (typescriptlang.org).](https://www.typescriptlang.org/docs/handbook/jsx.html#embedding-expressions) Retrieved July 6, 2023.- {listItems}