Tìm kiếm trang web

reactjs - Typescript React: Truy cập kiểu thuộc tính của component


Gói npm @types/react cho phép chúng ta sử dụng React trong các ứng dụng TypeScript của mình. Chúng ta định nghĩa các thành phần như

type Props = {...}

type State = {...}

export default class MyComponent extends React.Component<Props, State> {
}

ở đây chúng ta phải khai báo kiểu cho props và state của component (trong các biến kiểu).

Sau khi chúng tôi khai báo các kiểu đó, TypeScript sử dụng chúng để xác thực việc sử dụng component của chúng tôi (cấu trúc của các props được truyền vào).

Tôi muốn tạo một container bao quanh một thành phần như vậy. Container này sẽ tái sử dụng các props của thành phần. Nhưng để tạo một thành phần khác với cùng các props, tôi phải khai báo lại các kiểu cho props. Hoặc xuất chúng từ tệp thành phần gốc và nhập vào container:

// original file
export type Props = {...}

// container file
import MyComponent, { Props } from './original'

Nhưng tôi đã đang nhập MyComponent từ tệp đó. Thành phần này đã chứa thông tin về các props mà nó sử dụng (nhờ các biến kiểu trong React.Component).

Câu hỏi là Làm thế nào để tôi truy cập thông tin đó từ chính lớp component mà không cần xuất/nhập khẩu kiểu cho props một cách rõ ràng?

Tôi muốn một cái gì đó như:

import MyComponent from './MyComponent'

type Props = MyComponent.Props // <= here access the component prop types

export default class MyContainer extends React.Component<Props, {}> {}

Câu trả lời #1

2019: nhận thấy tất cả các câu trả lời ở trên đều khá lỗi thời nên đây là một câu trả lời mới.

Loại tra cứu

Với các phiên bản TS mới hơn, bạn có thể sử dụng các kiểu tra cứu.

type ViewProps = View['props']

Mặc dù rất tiện lợi, điều đó chỉ hoạt động với các thành phần lớp.

Props của React.Component

Các typedefs của React đi kèm với một tiện ích để trích xuất kiểu của props từ bất kỳ component nào.

type ViewProps = React.ComponentProps<typeof View>

type InputProps = React.ComponentProps<'input'>

Điều này dài dòng hơn một chút, nhưng không giống như giải pháp tra cứu loại:

  • ý định của nhà phát triển rõ ràng hơn
  • điều này sẽ hoạt động với cả các thành phần hàm và thành phần lớp

Tất cả những điều này làm cho giải pháp này trở thành an toàn nhất cho tương lai: nếu bạn quyết định chuyển từ các lớp sang hooks, bạn sẽ không cần phải tái cấu trúc bất kỳ mã khách hàng nào.

Câu trả lời #2

Bắt đầu từ TypeScript 2.8, bạn có thể sử dụng các kiểu điều kiện, ví dụ cho:

interface MyComponentProps { bar: string; }
declare const MyComponent: React.Component<MyComponentProps>;

interface MyComponentClassProps { bar: string; }
declare const MyComponentClass: React.ComponentClass<MyComponentClassProps>;

interface MyStatelessComponentProps { bar: string; }
declare const MyStatelessComponent: React.StatelessComponent<MyStatelessComponentProps>;

Chúng ta có thể định nghĩa các trợ giúp này:

type GetComponentProps<T> = T extends React.ComponentType<infer P> | React.Component<infer P> ? P : never

Và sử dụng chúng như sau:

// $ExpectType MyComponentProps
type MyComponentPropsExtracted = GetComponentProps<typeof MyComponent>

// $ExpectType MyComponentClassProps
type MyComponentClassPropsExtracted = GetComponentProps<typeof MyComponentClass>

// $ExpectType MyStatelessComponentProps
type MyStatelessComponentPropsExtracted = GetComponentProps<typeof MyStatelessComponent>

Cập nhật 2018-12-31: điều này hiện đã có sẵn trong các kiểu chính thức của React thông qua React.ComponentProps.

Bài viết liên quan