此typescript代码中如何避免变成never类型(never不能进行使用属性了)?

import React from 'react';
import logo from './logo.svg';
import './App.css';

import MonacoEditor from 'react-monaco-editor';
import { useRef, useState,useEffect }  from 'react';

function App() {

  const editorRef = useRef(null);
  const monacoRef = useRef(null);
  const decorationsRef = useRef([]);

  const handleEditorDidMount = (editor: any, monaco: any) => {
    editorRef.current = editor;
    monacoRef.current = monaco;

    // Add an event listener for cursor position changes
    editor.onDidChangeCursorSelection(() => {
      const selection = editor.getSelection();
      // if (selection.isEmpty()) {
      //   // Remove decorations if selection is empty
      //   editor.deltaDecorations(decorationsRef.current, []);
      //   return;
      // }
      
      const lineNumber = selection.positionLineNumber;
      const lineContent = editor.getModel().getLineContent(lineNumber);

      if (lineContent !== "") {
        // Add decoration if the line starts with 'var'
        const newDecorations = editor.deltaDecorations(decorationsRef.current, [
          {
            range: new monaco.Range(lineNumber, 1, lineNumber, 1),
            options: {
              isWholeLine: true,
              afterContentClassName: 'myAfterContentDecoration'
            }
          }
        ]);
        decorationsRef.current = newDecorations;
      } else {
        // Remove decorations if the line does not start with 'var'
        editor.deltaDecorations(decorationsRef.current, []);
      }
    });
  };
  useEffect(() => {
    // Define custom styles for the decorations
    const style = document.createElement('style');
    style.innerHTML = `
      .myAfterContentDecoration::after {
        content: ' // 备注';
        color: green;
        font-weight: bold;
      }
    `;
    document.head.appendChild(style);
  }, []);

  const clickButton = () => {
    if(monacoRef.current) {  // null
      console.log(monacoRef.current)  // never
    }
    
  }


  return (
    <div style={{'margin':'100px auto', 'width': '800px'}}>
    <MonacoEditor
        value={"112233"}
        editorDidMount={handleEditorDidMount}
      />

      <button onClick={clickButton}>点击</button>
    </div>
  );
}

export default App;

在代码:clickButton 里面, if(monacoRef.current) 这里是null,但是在console.log(monacoRef.current)里面是never
image.png

image.png

因为是never, 就不能点进行使用属性了。
请问这个问题应该如何处理呢?

阅读 983
avatarAI BotBETA

在你的 TypeScript 代码中,出现 never 类型的问题通常是因为 TypeScript 的类型推断系统在某些条件下无法确定一个变量确切的类型,从而将其推断为 never。然而,在你的特定例子中,monacoRef.current 被声明为 any 类型的引用(由于 useRef 的泛型参数未指定),并且你提到在 clickButton 函数中 monacoRef.current 被认为是 null,但在 console.log 时显示为 never。这实际上是一个误解或配置问题,因为 TypeScript 通常不会将 null 推断为 never

不过,你的代码中存在一个潜在的问题,即 monacoRef.current 可能在编辑器未完全挂载前就被访问(即 monacoRef.current 仍然是 null)。为了避免这个问题,你可以通过检查 monacoRef.current 是否为 nullundefined 来确保它已被正确设置:

const clickButton = () => {
  if (monacoRef.current !== null && monacoRef.current !== undefined) {
    console.log(monacoRef.current);  // 现在 monacoRef.current 不会是 never 类型
  } else {
    console.log('Monaco editor has not mounted yet.');
  }
};

此外,虽然 useRef 的泛型参数在这里被省略了,但最好明确指定它,以提供更好的类型安全性和更清晰的代码意图。由于你正在存储 monaco 实例,你可以尝试如下方式声明 monacoRef

const monacoRef = useRef<monaco.editor.IStandaloneCodeEditor | null>(null);

这样,TypeScript 就能更准确地推断 monacoRef.current 的类型,并在你尝试访问其属性或方法时提供编译时检查。

最后,关于你提到的 never 类型,这通常不是由简单的 null 检查引起的。如果你在某个地方看到了 never 类型,并且它导致了编译错误,那么很可能是你的类型逻辑在某个分支中导致了矛盾,使得 TypeScript 推断出没有任何可能的值能满足该类型(即 never)。然而,在你的这个例子中,问题更可能是由于误解了 TypeScript 的行为或错误地使用了 console.log 的结果解读。

2 个回答

向 useRef 添加泛型参数:

import { useRef } from 'react'

const a = useRef(null), b = useRef<number>(null)

function onClick() {
    if (a.current) {
        console.log(a.current) // never
    }

    if (b.current) {
        console.log(b.current) // number
    }
}
推荐问题
logo
Microsoft
子站问答
访问
宣传栏