Reputation: 6186
Having the following code snippet that works fine with React + Javascript:
import React, { useRef } from "react";
import Editor from "@monaco-editor/react";
function App() {
const editorRef = useRef(null);
function handleEditorDidMount(editor, monaco) {
editorRef.current = editor;
}
function showValue() {
alert(editorRef.current?.getValue());
}
return (
<>
<button onClick={showValue}>Show value</button>
<Editor
height="90vh"
defaultLanguage="javascript"
defaultValue="// some comment"
onMount={handleEditorDidMount}
/>
</>
);
}
export default App;
I need to use it in a React + Typescript app so I have to add types.
What type should be used for editor
?
Tried like this:
function handleEditorDidMount(editor: HTMLInputElement) {
editorRef?.current = editor;
}
function showValue() {
// eslint-disable-next-line no-alert
alert(editorRef?.current?.getValue());
}
For the first method, the error is:
The left-hand side of an assignment expression may not be an optional property access.ts(2779)
const editorRef: React.MutableRefObject<null>
For the second:
Property 'getValue' does not exist on type 'never'.ts(2339)
Any suggestions?
Upvotes: 5
Views: 3985
Reputation: 11
To solve the TypeScript issues you're encountering, you can destructure the OnMount
type from the Monaco editor package. The OnMount
type is the type of the onMount
prop, and you can extract the type for the editor by accessing the first parameter of the OnMount
type.
Here's how you can apply this solution:
import { Editor as MonacoEditor, type OnMount } from "@monaco-editor/react";
// Extract the type of the editor from the OnMount prop
type IStandaloneCodeEditor = Parameters<OnMount>[0];
...
const editorRef = useRef<IStandaloneCodeEditor | null>(null);
const handleEditorDidMount = (editor: IStandaloneCodeEditor) => {
editorRef.current = editor;
};
OnMount
type: This type represents the function signature for the onMount
callback. By using Parameters<OnMount>[0]
, we extract the first parameter of the onMount
function, which is the editor
instance, and assign it to the IStandaloneCodeEditor
type.useRef<IStandaloneCodeEditor | null>(null)
: This ensures that the editorRef
is typed correctly to hold a Monaco editor instance or null
initially.handleEditorDidMount
function: This function is typed to accept an editor instance of type IStandaloneCodeEditor
.Upvotes: 1
Reputation: 71
According to the official documentation, the monaco react library is using monaco-editor
as its peer dependency.
NOTE: For TypeScript type definitions, this package uses the monaco-editor package as a peer dependency. So, if you need types and don't already have the monaco-editor package installed, you will need to do so
In my case, I installed monaco-editor
as my dev dependency since I just need its type definitions. As @yilmaz specified, we can use the type editor.IStandaloneCodeEditor
for the ref.
import { editor } from 'monaco-editor';
...
const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null);
Upvotes: 0
Reputation: 49671
import type onMount
import MonacoEditor, { OnMount } from "@monaco-editor/react";
if you hover on onMount
:
type OnMount = (editor: monaco.editor.IStandaloneCodeEditor, monaco: Monaco) => void
use it on handleDidMount:
const handleEditorDidMount:OnMount=(editor) { editorRef?.current = editor; }
if you see the type,handleEditorDidMount
takes 2 args
const handleEditorDidMount:OnMount=(editor,_monaco) {
editorRef?.current = editor;
}
Since you are using OnMount
type, args type will be inferred by typescript:
editor: editor.IStandaloneCodeEditor
Upvotes: 7
Reputation: 1130
The returned type of useRef(null)
is React.MutableRefObject<null>
. But you want typescript to know you're gonna pass an input element to the ref, so you have to explicitily set its type const editorRef = useRef(null) as React.MutableRefObject<null | HTMLInputElement>;
editorRef.current
will always be defined, but the type of editorRef.current
is now null | HTMLInputElement
, because the type of current is the type you pass into the generic of React.MutableRefObject
.
Regarding this error.
The left-hand side of an assignment expression may not be an optional property access.ts(2779)
const editorRef: React.MutableRefObject<null>
editorRef.current
will always be defined. The value however can be null
as you have explicitily typed. So no need for the ?
Knowing this you can adjust your last part of code to
function showValue() {
// eslint-disable-next-line no-alert
alert(editorRef.current?.getValue());
}
Upvotes: 0