如何在TypeScript strictPropertyInitialization新选项下使用React refs?
strictPropertyInitialization for Bootstrap Popover When TypeScript’s strictPropertyInitialization flag is enabled, it enforces that all class properties are initialized either at declaration time or in the constructor. This often causes headaches with React refs, since they’re typically assigned later in the render method. Let’s walk through the solutions for your Popover component.
First, let’s assume your component had a ref declared like this (which would trigger the error):
export class Popover extends PureComponent<PopoverProps, object> { // This throws an error because popoverRef isn't initialized private popoverRef: React.RefObject<HTMLElement>; // ... rest of your component code (componentDidMount, render, etc.) }
Solution 1: Initialize the ref at declaration time
The simplest fix is to initialize the ref immediately when declaring it using React.createRef():
import * as React from "react" import { PureComponent } from "react"; import { EventUtil } from "appUtil/EventUtil"; export interface PopoverProps extends React.HTMLProps<HTMLElement>{ popoverTitle: string | Element | Function; popoverContent: string | Element | Function; container?: string; allowDefaultClick?: boolean; } export class Popover extends PureComponent<PopoverProps, object> { // Initialize ref right here to satisfy TypeScript private popoverRef = React.createRef<HTMLElement>(); componentDidMount() { // Safely access the ref (always check if current exists!) if (this.popoverRef.current) { // Initialize Bootstrap popover $(this.popoverRef.current).popover({ title: this.props.popoverTitle, content: this.props.popoverContent, container: this.props.container || "body", }); } } componentWillUnmount() { // Clean up the popover to avoid memory leaks if (this.popoverRef.current) { $(this.popoverRef.current).popover("dispose"); } } render() { // Attach the ref to your target element return ( <div ref={this.popoverRef} {...this.props}> {this.props.children} </div> ); } }
Solution 2: Initialize the ref in the constructor
If you prefer to handle initialization in the constructor, that works too:
export class Popover extends PureComponent<PopoverProps, object> { private popoverRef: React.RefObject<HTMLElement>; constructor(props: PopoverProps) { super(props); // Initialize ref inside the constructor this.popoverRef = React.createRef<HTMLElement>(); } // ... rest of your component code }
Solution 3: Use the definite assignment assertion (!)
If you’re absolutely certain the ref will be attached before it’s used (e.g., your render method always creates the element with the ref), you can use the ! operator to tell TypeScript the property will be initialized later:
export class Popover extends PureComponent<PopoverProps, object> { // The ! tells TypeScript this will be initialized before use private popoverRef!: React.RefObject<HTMLElement>; componentDidMount() { // Still safe to check if current exists to avoid runtime errors if (this.popoverRef.current) { $(this.popoverRef.current).popover({ /* your options */ }); } } render() { return <div ref={this.popoverRef} {...this.props}>{this.props.children}</div>; } }
Key Notes
- Always check if
popoverRef.currentis notnullorundefinedbefore accessing it—even if you use the definite assignment assertion. This prevents runtime errors if the ref isn’t attached for some reason. - Don’t forget to clean up the Bootstrap popover in
componentWillUnmountto avoid memory leaks.
内容的提问来源于stack exchange,提问作者Shorn

