创建接口/类型别名,其中包含来自联合类型的详尽属性列表?

问题描述

想象一下我有这个数组,这是我的动作名称的“真相之源”:

var slider = document.getElementById("myRange");
var output = document.getElementById("demo");
var prezzo = document.getElementById("demoprezzo");
output.innerHTML = slider.value; // display the default slider value

// Update the current slider value (each time you drag the slider handle)
slider.oninput = function() {
  output.innerHTML = this.value;
//  if (slider = 12) {    I can't go on 
   
}

// This is the function to import data from acf plugin. It works
//<?PHP

//$variable = get_field('prezzo');

//echo $variable
  
//?>

现在我想要一个接口/类型,它应该具有所有这些属性(穷尽),例如:

<h1>Durata</h1>
<div class="slidecontainer">
  <input type="range" min="12" max="36" value="12" step="12" class="slider" id="myRange">
  <p>Value: <span id="demo"></span></p>
  <p>Prezzo: <span id="demoprezzo"></span></p>
</div>

我可以从const ACTION_NAMES = ["ACTION_1","ACTION_1","ACTION_3"] as const; // I'M USING "as const" SO I CAN GET A UNION TYPE OUT OF IT type ACTION_NAMES = typeof ACTION_NAMES[number]; // THIS IS "ACTION_1" | "ACTION_2" | "ACTION_3" type SOME_TYPE = { [key: string]: unkNown } interface ACTION_PAYLOADS { // Could ALSO USE type alias HERE ACTION_1: {propA: string,propB: number},ACTION_2: {propC: boolean},ACTION_3: {propD: string} } 接口开始使用任何类型,以便Typescript确保所有extend属性都存在,并且所有值都为{{1 }} ACTION_PAYLOADS类型?

这个想法是,如果我缺少ACTION_1 2 and 3属性之一,并且其中一个值不是extend类型,Typescript在理想情况下也应该抱怨。另外,它也不允许我添加任何其他属性,例如SOME_TYPE

感觉就像我在检查类型。但是我不能使用某些映射类型吗?有没有办法做到这一点?

解决方法

如果您的界面不符合所需的约束,则可以使用一些帮助程序类型来触发编译器错误。看起来像这样:

type Extends<T extends U,U> = void;
type MutuallyExtends<T extends U,U extends V,V = T> = void;

type CheckKeysOfActionPayloads =
    MutuallyExtends<keyof ACTION_PAYLOADS,ACTION_NAMES>; // ok
type CheckValuesOfActionPayloads =
    Extends<ACTION_PAYLOADS[ACTION_NAMES],SOME_TYPE>; // ok

在这里,CheckKeysOfActionPayloads仅在ACTION_PAYLOADS和类型ACTION_NAMES的键相互延伸时才编译...对于文字的并集,这意味着它们需要相同。

并且只有CheckValuesOfActionPayload(在ACTION_PAYLOADS键处的值)可分配给ACTION_NAMES的情况下,SOME_TYPE才会编译。


为了具体起见,我将SOME_TYPE更改为可能会失败的内容,同时还要确保ACTION_NAMES中包含"ACTION_2"(与示例代码相对) :

const ACTION_NAMES = ["ACTION_1","ACTION_2","ACTION_3"] as const;
type ACTION_NAMES = typeof ACTION_NAMES[number];
type SOME_TYPE = {
    [key: string]: string | number | boolean
}

让我们看看如果弄乱ACTION_PAYLOADS会发生什么。首先,如果我们错过钥匙:

interface ACTION_PAYLOADS {
    ACTION_1: { propA: string,propB: number },// where's ACTION_2?
    ACTION_3: { propD: string }
}

type CheckKeysOfActionPayloads =
    MutuallyExtends<keyof ACTION_PAYLOADS,ACTION_NAMES>; // error!
//      ----------------------------------> ~~~~~~~~~~~~
// Type "ACTION_2" is not assignable to type "ACTION_1" | "ACTION_3"

或者如果我们有额外的钥匙:

interface ACTION_PAYLOADS {
    ACTION_1: { propA: string,ACTION_2: { propC: boolean },ACTION_3: { propD: string },ACTION_4: { propE: number } // what's this?
}

type CheckKeysOfActionPayloads =
    MutuallyExtends<keyof ACTION_PAYLOADS,ACTION_NAMES>; // error!
// ---------------> ~~~~~~~~~~~~~~~~~~~~~
// Type "ACTION_4" is not assignable to type "ACTION_1" | "ACTION_2" | "ACTION_3"

最后,如果键正确但值错误:

interface ACTION_PAYLOADS {
    ACTION_1: { propA: string,ACTION_2: { propC: Date },// what's this?
    ACTION_3: { propD: string }
}

type CheckValuesOfActionPayloads =
    Extends<ACTION_PAYLOADS[ACTION_NAMES],SOME_TYPE>; // error!
// -------> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Type 'Date' is not assignable to type 'string | number | boolean'

您会看到在所有这些情况下,您都会得到一个错误,希望可以用来帮助您修复代码。

Playground link to code

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...