有没有办法既解构函数参数,又保留对参数的命名引用?

Is there a way to both destructure a function parameter, and keep a named reference to the parameter?

在 React 无状态功能组件中,我们通常会这样写:

export function MyCompoment({
    title, 
    foo, 
    bar
}) {
    return <div> title: {title}, ...</div>
}

我们立即将 props 对象解构为其变量。

现在我用的是Material-UI makeStyles hook,我也在用TypeScript,我现在的使用方式是这样的。

const useStyles = makeStyles((theme : Theme ) =>({
     root: ({foo} : MyComponentProps) => ({
         content: foo
     })
}); 

interface MyComponentProps  {
    title: string; 
    foo: string; 
    bar: string; 
}
export function MyCompoment({
    title, 
    foo, 
    bar
} : MyComponentProps) {
    const classes = useStyles({
        title,
        foo, 
        bar
    }); 
    return <div> title: {title}, ...</div>
}

你可以看到问题 - 我必须重复 props 变量名称才能传递到 类。

我认为避免这种情况的最好方法是这样写:

export function MyCompoment(props: MyComponentProps) {
    const {
       title, 
       foo, 
       bar
    }  = props; 
    const classes = useStyles(props); 
    return <div> title: {title}, ...</div>
}

但这比我想要的要乱一些。

我想知道是否可以这样做:

export function MyCompoment({
       title, 
       foo, 
       bar
    }  = props : MyComponentProps) {

    const classes = useStyles(props); 
    return <div> title: {title}, ...</div>
}

我知道我很挑剔,只是想知道。

Is there a way to both destructure a function parameter, and keep a named reference to the parameter?

没有。您需要分两步完成,因为您需要将 props 作为单个参数,然后再对它们进行解构。

没有(大部分)


来自语法:

很难证明否定,所以我不得不去语法。

据我所知,Typescript 没有提供 javascript 没有的任何额外的解构能力,所以我只针对 javascript.

回答这个问题

在 ES6 语法中,单个函数参数无法在一个参数中同时被析构并在参数列表中指定名称。

如果你查看 FormalParameterES6 grammar,它是参数列表中的一个,你会发现它只能是 BindingElement,它是SingleNameBindingBindingPattern 中的一个——不能同时使用。绑定模式只能进行解构,单名称绑定只能分配给一个值,因此无法同时进行。

(请注意,我链接的语法只是某人放在 github 上的要点。我不认为有人会 post github 上的误导性 ES6 语法,但如果你如果您持怀疑态度,您可以随时检查不太方便的官方语法。)

可能还有其他一些我错过的疯狂方法,但我以前从未见过,我会感到非常惊讶。


如果你真的想...

你"best way you can think of"也是我能想到的最好的办法了。你应该这样做。

虽然我不喜欢回答"no",所以如果你真的想在参数列表中得到它,你可以做一些不愉快的事情。如果你这样做:

function assignAndDestructure(props, { foo, bar } = props) {
    // props, foo, and bar will all be assigned
}

哪种符合您的标准。然而,它创建了一个可选的第二个参数,调用者可以滥用它来破坏你的解构。您可以通过将其分配给 Typescript 中没有该参数的类型来隐藏它,但这仍然存在风险。


综上所述,没有好办法,只有坏办法。按照你提到的 "best you can think of."

我不明白为什么会有人想出这个答案... 您始终在 arguments.

中引用参数
function _test({ a, b }){ 
  var arg = arguments[0];
  console.log("a=",a,"b=",b,"arg=",arg);
}

测试时产生此输出:

_test({ a:23, b:"asd", c:"$" })
// a= 23 b= asd arg= { a: 23, b: 'asd', c: '$' }

在你的情况下,可以这样做。

export function MyCompoment({
       title, 
       foo, 
       bar
    }) {
    const props = arguments[0];
    const classes = useStyles(props); 
    return <div> title: {title}, ...</div>
}