I'm sure someone out there has already thought of this. But I stumbled on it when looking at errors.As statements in a contribution I was making to Flipt.
UPDATE: I found an existing proposal to add this to the standard library and in there it appears this was called out in the generic design proposal itself: https://github.com/golang/go/issues/51945.

TL;DR

This function is handy for brevity and to avoid a potential runtime panic:
func As[E error](err error) (e E, _ bool) {
    return e, errors.As(err, &e)
}

errors.As

If you've ever used the standard-libraries errors.As function, you might be familiar with its quirks.
Firstly, you're going to have to explicitly declare a variable and its type on one line. Only then can you create a pointer to that variable and pass it to errors.As.
package main

import "errors"

type MyError string

func (e MyError) Error() string {
    return string(e)
}

func returnsMyError() error {
    return fmt.Errorf("wrapped my error: %w", MyError("my error"))
}

func main() {
    var merr MyError
    if errors.As(returnsMyError(), &merr) {
        fmt.Println("The root of the error was a MyError type:", merr)
    } 
}
The program above prints:
The root of the error was a MyError type: my error
Note that in main() we first define the variable and type we're interested in. Then on the subsequent line we create a pointer to this variable and pass it to errors.As.
The ergonomics are not great here.
However, there are also hazards if your custom error is implemented on a pointer to a type.
type MyError struct {
    Message string
}

func (e *MyError) Error() string {
    return e.String()
}
In this situation it can be easy when calling errors.As to miss the fact that you need to pass it a **MyError (Congrats, you're one step closer to becoming a three-star programmer). Leading to accidents like the following.
// ...
func returnsMyError() error {
    return &MyError{Message: "my error"}
}

func main() {
    var merr MyError
    if errors.As(returnsMyError(), &merr) {
        fmt.Println("The root of the error was a MyError type:", merr)
    } 
}
Which leads to a runtime panic:
panic: errors: *target must be interface or implement error

goroutine 1 [running]:
errors.As({0x4bb008, 0xc000094230}, {0x48d200, 0xc000094220?})
	/go/src/errors/wrap.go:89 +0x3df
You must be sure to pass a pointer to an error implementation.
func main() {
    var merr *MyError // *MyError is the error implementation not MyError
    if errors.As(returnsMyError(), &merr) {
        fmt.Println("The root of the error was a MyError type:", merr)
    } 
}

Solution

Generics (introduced in Go 1.18) provide a handy way to one-line errors.As and it provides compile-time safety to avoid this panic.
All you need is this handful of lines:
import "errors"

// ...

func As[E error](err error) (e E, _ bool) {
    return e, errors.As(err, &e)
}
With this you can one-line the declaration and assertion like so:
// ...

func main() {
	if merr, match := As[MyError](returnsMyError()); match {
		fmt.Println("The root of the error was a MyError type:", merr)
	}
}
  1. No more pesky variable declaration required before the conditional.
  2. If your type implements Error() over a pointer you can't mistakenly attempt to call As with the non-pointer type.
See the what the following attempt to make the mistake in (2) does:
package main

import (
	"errors"
	"fmt"
)

func As[E error](err error) (e E, _ bool) {
	return e, errors.As(err, &e)
}

type MyError string

// Error() is implemented over a *MyError (pointer to MyError)
func (e *MyError) Error() string {
	return string(*e)
}

func returnsMyErrorPointer() error {
	err := MyError("my errors")
	return &err
}

func main() {
	if merr, match := As[MyError](returnsMyErrorPointer()); match {
		fmt.Println("The root of the error was a MyError type:", merr)
	}
}
This program actually fails at compile time with:
./prog.go:24:23: MyError does not implement error (Error method has pointer receiver)
Removing the runtime panic situation altogether.

Final Thoughts

This is not a perfect solution. There still exists one particular trap. It is a trap that exists in the standard library errors.As too.
When you don't accept a pointer to a type when implementing Error() then the compiler will accept that *YourErrorType implements error still. Because a method on non-pointer type can be called on a pointer to it. The pointer is just dereferenced before invoking the function (Error() in this case). So one final subtle easy to make mistake remains.
type MyError string

func (e MyError) Error() string {
    return string(e)
}

func returnsMyErrorPointer() error {
    err := MyError("my errors")
    return &err
}

func main() {
	if merr, match := As[MyError](returnsMyErrorPointer()); match {
		fmt.Println("The root of the error was a MyError type:", merr)
        return
	}

    fmt.Println("Does not match")
}
This compiles and prints Does not match. Because it is *MyError which is returned, and not MyError. This is an easy mistake to make. Sadly I think this is unavoidable.