最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Property 'selectionStart' does not exist on type 'EventTarget' - Stack Overflow

programmeradmin5浏览0评论

I am using selectionStart and selectionEnd in order to get the starting and ending point of a text selection.

Code:

However, I am struggling to defined the type of the event on which they can be called on. If I use any, the code works properly but I would prefer to know the right event.

I tried with these types: Element React.SyntheticEvent<HTMLDivElement> <HTMLDivElement> with no luck

export default function App() {
  const [startText, setStartText] = useState<number | undefined>();
  const [endText, setEndText] = useState<number | undefined>();

  const handleOnSelect = (event: any) => { <--- I CANNOT FIND THE RIGHT EVENT TYPE
    setStartText(event.target.selectionStart);
    setEndText(event.target.selectionEnd);
  };

  return (
    <Grid container direction="column" className="App">
      You can type here below:
      <TextField
        value={"This is a example, select a word from this string"}
        onSelect={(event) => handleOnSelect(event)}
      />
      <br />
      <Grid item>The selected word starts at character: {startText}</Grid>
      <Grid item>The selected word ends at character: {endText}</Grid>
    </Grid>
  );
}

I am using selectionStart and selectionEnd in order to get the starting and ending point of a text selection.

Code: https://codesandbox.io/s/busy-gareth-mr04o

However, I am struggling to defined the type of the event on which they can be called on. If I use any, the code works properly but I would prefer to know the right event.

I tried with these types: Element React.SyntheticEvent<HTMLDivElement> <HTMLDivElement> with no luck

export default function App() {
  const [startText, setStartText] = useState<number | undefined>();
  const [endText, setEndText] = useState<number | undefined>();

  const handleOnSelect = (event: any) => { <--- I CANNOT FIND THE RIGHT EVENT TYPE
    setStartText(event.target.selectionStart);
    setEndText(event.target.selectionEnd);
  };

  return (
    <Grid container direction="column" className="App">
      You can type here below:
      <TextField
        value={"This is a example, select a word from this string"}
        onSelect={(event) => handleOnSelect(event)}
      />
      <br />
      <Grid item>The selected word starts at character: {startText}</Grid>
      <Grid item>The selected word ends at character: {endText}</Grid>
    </Grid>
  );
}
Share Improve this question edited Nov 21, 2022 at 8:06 sideshowbarker 88.2k29 gold badges215 silver badges211 bronze badges asked Mar 19, 2021 at 14:27 MagofocoMagofoco 5,4667 gold badges43 silver badges85 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 14

This is a tricky one because the material-ui TextField ponent involves multiple nested nodes. The argument that is passed to the onSelect function is a div. However the event itself occurs on an input inside the div.

const handleOnSelect = (event: React.SyntheticEvent<HTMLDivElement, Event>) => {
    console.log(event.target, event.currentTarget);
};

This logs the input and then the div.

Using event.currentTarget gets very specific Typescript information. We know that it is an HTMLDivElement. But the div doesn't have the properties selectionStart and selectionEnd that we want to access. Those exist on the input.

event.target gives us a very vague type for an EventTarget. We don't know that the target is an input.

One option is to verify the element at runtime.

const handleOnSelect = (event: React.SyntheticEvent<HTMLDivElement, Event>) => {
    if ( event.target instanceof HTMLInputElement ) {
        setStartText(event.target.selectionStart);
        setEndText(event.target.selectionEnd);
    }
};

Since you know that the event will always occur on an HTMLInputElement, I think it's safe to make an assertion.

const handleOnSelect = (event: React.SyntheticEvent<HTMLDivElement, Event>) => {
    const target = event.target as HTMLInputElement;
    setStartText(target.selectionStart);
    setEndText(target.selectionEnd);
};

Note that selectionStart and selectionEnd properties use null instead of undefined. So you'll want to either change your state type to <number | null> or replace null with undefined by using null coalescing event.target.selectionStart ?? undefined.

发布评论

评论列表(0)

  1. 暂无评论