主頁 > 資料庫 > 如何用強型別的restparams鍵入構造器選項物件的引數

如何用強型別的restparams鍵入構造器選項物件的引數

2021-10-22 07:28:21 資料庫

我不知道如何在Typescript中打字。

我有一個正在移植的Javascript類,在此簡化:

我有一個正在移植的Javascript類。

class A {
    constructor ({
        a = 'hi',
        b = 5,
        ...其余
    } = {}) {
        this.a = a
        this.b = b
        this.extra = rest
    }

建構式接收一個帶有一些默認值的選項物件,并將其余部分收集到一個物件中。那個rest params物件應該是扁平的,沒有嵌套的物件或陣列,并且需要是JSON可序列化的,并且是完全可選的。但如果它存在的話,我想為呼叫者提供一個機會,讓它成為良好的型別。所以我定義了幾個型別:

type KnownStuff = {
    a: string
    b: 數字
}

型別 FlatJSONCompatibleObject = {
    [k: string]: string | number | boolean | null

此外,我希望能夠為其余部分指定一些額外的引數:

我希望能夠為其余部分指定一些額外的引數。

type Test = {
    c: boolean
    d: 'a' | 'b'

所以我試著做了以下的作業:

class A < T extends FlatJSONCompatibleObject = {}> { a: string b: 數字 extra: T 構造器({ a = 'hi', b = 5, ...其余 }: Partial<KnownStuff> & T = {}) { this.a = a this.b = b this.extra = rest // failed } }

這是不可能的,因為泛型并不受限制。所以接下來:

class Foo < T extends Omit<FlatJSONCompatibleObject, keyof KnownStuff> > {
    a: string
    b: 數字
    extra: T
    構造器({
        a = 'hi',
        b = 5,
        ...其余
    }: Partial<KnownStuff> & T = {}) {
        this.a = a
        this.b = b
        this.extra = rest
    }

但這無法編譯,我無法獲得正確的通用約束。

我最接近的方法是這樣的:

class Bar< T extends Omit<FlatJSONCompatibleObject, keyof KnownStuff> > {
    a: string
    b: 數字
    extra: Omit<FlatJSONCompatibleObject, keyof KnownStuff>
    constructor({
        a = 'hi',
        b = 5,
    }: Partial<KnownStuff> = {}, rest: Partial<T> = {}) {
        this.a = a
        this.b = b
        this.extra = rest
    }

這可以編譯,但改變了簽名,我真的想避免這樣做,因為這是作業需要,而且已經被其他多個團隊廣泛使用。這也是錯誤的:

const c = new Bar<Test>()

這應該是失敗的,因為引數上的屬性不是可選的,但我不得不使用Partial<T>來能夠分配默認的空物件。我懷疑我在這棵完全錯誤的樹上吠叫,這就是為什么我提出這個問題。

因此,問題的約束條件是:

  1. 類需要一個帶有一些已知屬性的選項物件。
  2. 這些已知的屬性應該都有默認值,new Whatever()應該可以。
  3. 類可以接受物件中的一些額外屬性。
  4. 如果存在額外的東西,必須是JSON兼容的,并且是平面的(沒有嵌套的物件或陣列)。
  5. 該類的用戶應該能夠傳遞一個型別引數,這樣額外的東西就有了一個明確定義的和編譯器強制的型別,也就是說,new Whatever<SomeTypeWithRequiredProperties>()不應該作業。
  6. 我真的不想改變(從Javascript的角度)建構式的簽名,因為這已經被廣泛使用了。

我怎樣才能打出這樣的字?

Playground if it helps

和一個(不正確,但希望能給出要點)測驗線束:

//class test harnessfunction test<T extends FlatJSONCompatibleObject = {}> (C: {new <U extends FlatJSONCompatibleObject = {}> (opts? : Partial<KnownStuff> & U)。) LP<T>}) { //應該作業const t1 = new C() 。 t1.extras //應該是'{}'const t2 = new C<{c: boolean}>({c: true}) 。 t2.extras.c // should be true. //應該是編譯錯誤const t3 = new C<{c: boolean}>()。 const t4 = new C<{c: boolean}>({d: 4}) 。

uj5u.com熱心網友回復:

我將此作為答案發布(而不是對問題的編輯),因為它至少部分地回答了問題,但我不會接受它,因為a. 我并不完全理解它為什么有效,b. 我只能讓它對函式起作用,而不是對類的構造器起作用。由于 T.J. Crowder 在評論中的幫助,我偶然發現了這個部分解決方案。

如果我們這樣定義一個介面:

type LP<T extends FlatJSONCompatibleObject> = {
    a: string
    b: 數字
    extras: T

然后像這樣一個多載函式:

function bar)。LP<{}>
function bar<T extends FlatJSONCompatibleObject> (opts: Partial<KnownStuff> & T)。) LP<T>
function bar(opts? : Partial<KnownStuff> )。LP<{}>
{
    const {
        a = 'hi'/span>,
        b = 5,
        ...額外
    } = opts || {};
    if (opts) {
        return {
            a,
            b,
            額外的
        }
    } else {
        return {
            a,
            b,
            extras: {}.
        }
    }
}

const bar1 = bar() 。
bar1.extras // {}

const bar2 = bar<{c: boolean}>({c: true)
bar2.extras.c // boolean.

const bar3 = bar<{c: boolean}>() //編譯錯誤const bar4 = bar<{c: boolean}>({d: boolean}) //編譯錯誤

這可以作業,但我不能讓它對一個類起作用:

這可以作業。

class Foo < T extends FlatJSONCompatibleObject> {
    public a: string
    public b: 數字
    // public extras: T | {}
    public extras: T

    constructor()
    constructor(opts: Partial<KnownStuff> & T)
    constructor(opts? : Partial<KnownStuff>)
    {
        const {
            a = 'hi'/span>,
            b = 5,
            ...額外
        } = opts || {};
        this.a = a
        this.b = b
        if (opts) {
            this.extras = extras //錯誤
        } else {
            this.extras = {}。//錯誤。
        }
    }
}

盡管我可以通過讓額外的東西成為一個明確的第二引數來接近它:

class Bar< T extends FlatJSONCompatibleObject> { public a: string public b: 數字 public extras: T constructor() constructor(opts: Partial<KnownStuff> , extras: T) constructor(opts? Partial<KnownStuff>, extras?: never) { const { a = 'hi'/span>, b = 5.. } = opts || {} this.a = a this.b = b if (extras) { this.extras = extras } else { this.extras = {}。//錯誤!。 } } }

我似乎仍然無法獲得正確的多載。

Playground

uj5u.com熱心網友回復:

TL;DR

你目前無法用100%型別安全的TypeScript做到這一點。

詳情:

我的 TS 之旅還很早,但我認為這可能是一個案例。我可以做到引數是可選的,但如果你提供了一個具有必要屬性的型別引數,它就不會強制要求有一個引數(下面的#1)。或者我可以做到你沒有默認的引數(盡管有一個相對無害的@ts-ignore我寧愿避免)(下面的#2)。或者在我之前的一個嘗試上稍作改變,就真的接近了(下面的#3),但是extra的型別是{}|x而不是{}。|x,而不僅僅是x。我聯系了Titian Cernicova Dragomir,他確認在今天的TypeScript中你無法做到這一切,并提供了下面的#4,但是和我的#1一樣,當你提供一個型別引數時,它也沒有強制執行這個引數(同時,extra的型別最終是Partial<something>或者Partial<{}>)。

主要的問題是你標記出來的那個問題。你不能將{}分配給一個通用型別的屬性,因為該通用型別的具體型別可能不允許{}

所以很遺憾,看起來這將是一個選擇最接近的東西的問題。

#1

這是一個不能正確處理new A<something>()的問題:

Playground link

type KnownStuff = {
    a: 字串: a.
    b: 數字。
}

type FlatJSONCompatibleObject = {
    [k: string] 。string | number | boolean | null >。
}

type Test = {
    c: boolean: c.
    d: 'a' | 'b'
}

class A < Extra extends FlatJSONCompatibleObject = {}> {
    a: 字串b: 
    extra: Extra: extra.
    constructor()。
    constructor (props: Partial<KnownStuff> & Extra)。)
    constructor (props? : any) {
        const {a = 'hi', b = 5, ... extra} = props ? {}
        this.a = a
        this.b = b
        this.extra = extra
    }
}

const a1 = new A() // All good
a1.extra // type is {}

const a2 = new A<{c: boolean}>({d: "hi"}) // Error as desired.
a2.extra // type is {c: boolean}

const a3 = new A<{c: boolean}>() // No error :-()
a3.extra // Type is {c: boolean}

const a4 = new A<{c: boolean}>({c: true}) // All good
a3.extra // type is {c: boolean}

#2

這是一個不允許向建構式傳遞任何引數的建構式:

Playground link

type KnownStuff = {
    a: 字串: a.
    b: 數字。
}

type FlatJSONCompatibleObject = {
    [k: string] 。string | number | boolean | null >。
}

type Test = {
    c: boolean: c.
    d: 'a' | 'b'
}

class A < Extra extends FlatJSONCompatibleObject = {}> {
    a: 字串b: 
    extra: Extra: extra.
    constructor ({a = 'hi', b = 5, ... extra}。Partial<KnownStuff> & Extra) {
        this.a = a
        this.b = b
        //@ts-ignore.
        this.extra = extra
    }
}

//不再相關// const a1 = new A()
// a1.extra // Type is {}

const a2 = new A<{c: boolean}>({d: "hi"}); // Error as desired.
a2.extra // type is {c: boolean}.

const a3 = new A<{c: boolean}>(); // Error as desired
a3.extra // type is {c: boolean}

const a4 = new A<{c: boolean}>({c: true}); // All good
a3.extra // type is {c: boolean}

#3

這就是你為extra提供了一個尷尬的型別,X | {}而不是僅僅是X

Playground link/a>

type KnownStuff = {
    a: 字串: a.
    b: 數字。
}

type FlatJSONCompatibleObject = {
    [k: string] 。string | number | boolean | null >。
}

type Test = {
    c: boolean: c.
    d: 'a' | 'b'
}

class A < Extra extends FlatJSONCompatibleObject = {}> {
    a: 字串b: 
    extra: extra | {}。
    constructor (props? Partial<KnownStuff> & Extra) {
        if (props) {
            const {a = 'hi', b = 5, ... extra} = props
            this.a = a
            this.b = b
            this.extra = extra
        } else {
            this.a = 'hi'.
            this.b = 5.
            this.extra = {} 。
        }
    }
}

const a1 = new A() // All good
a1.extra // type is {}

const a2 = new A<{c: boolean}>({d: "hi"}) // Error as desired.
a2.extra // type is {c: boolean} | {}

const a3 = new A<{c: boolean}>() //錯誤如愿以償。
a3.extra // type is {c: boolean} | {}

const a4 = new A<{c: boolean}>({c: true}) // All good
a3.extra // type is {c: boolean}}. | {}

#4

Titian Cernicova Dragomir的那個有new A<something>()的問題#1有,而extra的型別最后是Partial<{}>或者Partial<something>

Playground link

type KnownStuff = {
    a: 字串: a.
    b: 數字。
}

type FlatJSONCompatibleObject = {
    [k: string] 。string | number | boolean | null >。
} | {}

type Test = {
    c: boolean: c.
    d: 'a' | 'b'
}

class A <T extends FlatJSONCompatibleObject ={}> {
    a: 字串b: 
    extra: Partial<T>
    constructor({
        a = 'hi'/span>,
        b = 5,
        ...其余
    }: Partial<KnownStuff> & Partial<T> ={}) {
        this.a = a
        this.b = b
        this.extra = rest as Partial< T>
    }
}

const a1 = new A() // All good
a1.extra // type is Partial<{}>

const a2 = new A<{c: boolean}>({d: "hi"}) // Error as desired.
a2.extra //Type is Partial<{c: boolean}>/span>

const a3 = new A<{c: boolean}>() // No error :-()
a3.extra //Type is Partial<{c: boolean}>/span>

const a4 = new A<{c: boolean}>({c: true}) // All good
a3.extra //Type is Partial<{c: boolean}>/span>

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/330168.html

標籤:

上一篇:Java方法接受不同的功能介面型別--可能嗎?

下一篇:在抽象類Typescript的建構式中創建新的通用類

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • GPU虛擬機創建時間深度優化

    **?桔妹導讀:**GPU虛擬機實體創建速度慢是公有云面臨的普遍問題,由于通常情況下創建虛擬機屬于低頻操作而未引起業界的重視,實際生產中還是存在對GPU實體創建時間有苛刻要求的業務場景。本文將介紹滴滴云在解決該問題時的思路、方法、并展示最終的優化成果。 從公有云服務商那里購買過虛擬主機的資深用戶,一 ......

    uj5u.com 2020-09-10 06:09:13 more
  • 可編程網卡芯片在滴滴云網路的應用實踐

    **?桔妹導讀:**隨著云規模不斷擴大以及業務層面對延遲、帶寬的要求越來越高,采用DPDK 加速網路報文處理的方式在橫向縱向擴展都出現了局限性。可編程芯片成為業界熱點。本文主要講述了可編程網卡芯片在滴滴云網路中的應用實踐,遇到的問題、帶來的收益以及開源社區貢獻。 #1. 資料中心面臨的問題 隨著滴滴 ......

    uj5u.com 2020-09-10 06:10:21 more
  • 滴滴資料通道服務演進之路

    **?桔妹導讀:**滴滴資料通道引擎承載著全公司的資料同步,為下游實時和離線場景提供了必不可少的源資料。隨著任務量的不斷增加,資料通道的整體架構也隨之發生改變。本文介紹了滴滴資料通道的發展歷程,遇到的問題以及今后的規劃。 #1. 背景 資料,對于任何一家互聯網公司來說都是非常重要的資產,公司的大資料 ......

    uj5u.com 2020-09-10 06:11:05 more
  • 滴滴AI Labs斬獲國際機器翻譯大賽中譯英方向世界第三

    **桔妹導讀:**深耕人工智能領域,致力于探索AI讓出行更美好的滴滴AI Labs再次斬獲國際大獎,這次獲獎的專案是什么呢?一起來看看詳細報道吧! 近日,由國際計算語言學協會ACL(The Association for Computational Linguistics)舉辦的世界最具影響力的機器 ......

    uj5u.com 2020-09-10 06:11:29 more
  • MPP (Massively Parallel Processing)大規模并行處理

    1、什么是mpp? MPP (Massively Parallel Processing),即大規模并行處理,在資料庫非共享集群中,每個節點都有獨立的磁盤存盤系統和記憶體系統,業務資料根據資料庫模型和應用特點劃分到各個節點上,每臺資料節點通過專用網路或者商業通用網路互相連接,彼此協同計算,作為整體提供 ......

    uj5u.com 2020-09-10 06:11:41 more
  • 滴滴資料倉庫指標體系建設實踐

    **桔妹導讀:**指標體系是什么?如何使用OSM模型和AARRR模型搭建指標體系?如何統一流程、規范化、工具化管理指標體系?本文會對建設的方法論結合滴滴資料指標體系建設實踐進行解答分析。 #1. 什么是指標體系 ##1.1 指標體系定義 指標體系是將零散單點的具有相互聯系的指標,系統化的組織起來,通 ......

    uj5u.com 2020-09-10 06:12:52 more
  • 單表千萬行資料庫 LIKE 搜索優化手記

    我們經常在資料庫中使用 LIKE 運算子來完成對資料的模糊搜索,LIKE 運算子用于在 WHERE 子句中搜索列中的指定模式。 如果需要查找客戶表中所有姓氏是“張”的資料,可以使用下面的 SQL 陳述句: SELECT * FROM Customer WHERE Name LIKE '張%' 如果需要 ......

    uj5u.com 2020-09-10 06:13:25 more
  • 滴滴Ceph分布式存盤系統優化之鎖優化

    **桔妹導讀:**Ceph是國際知名的開源分布式存盤系統,在工業界和學術界都有著重要的影響。Ceph的架構和演算法設計發表在國際系統領域頂級會議OSDI、SOSP、SC等上。Ceph社區得到Red Hat、SUSE、Intel等大公司的大力支持。Ceph是國際云計算領域應用最廣泛的開源分布式存盤系統, ......

    uj5u.com 2020-09-10 06:14:51 more
  • es~通過ElasticsearchTemplate進行聚合~嵌套聚合

    之前寫過《es~通過ElasticsearchTemplate進行聚合操作》的文章,這一次主要寫一個嵌套的聚合,例如先對sex集合,再對desc聚合,最后再對age求和,共三層嵌套。 Aggregations的部分特性類似于SQL語言中的group by,avg,sum等函式,Aggregation ......

    uj5u.com 2020-09-10 06:14:59 more
  • 爬蟲日志監控 -- Elastc Stack(ELK)部署

    傻瓜式部署,只需替換IP與用戶 導讀: 現ELK四大組件分別為:Elasticsearch(核心)、logstash(處理)、filebeat(采集)、kibana(可視化) 下載均在https://www.elastic.co/cn/downloads/下tar包,各組件版本最好一致,配合fdm會 ......

    uj5u.com 2020-09-10 06:15:05 more
最新发布
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:33:24 more
  • MySQL中binlog備份腳本分享

    關于MySQL的二進制日志(binlog),我們都知道二進制日志(binlog)非常重要,尤其當你需要point to point災難恢復的時侯,所以我們要對其進行備份。關于二進制日志(binlog)的備份,可以基于flush logs方式先切換binlog,然后拷貝&壓縮到到遠程服務器或本地服務器 ......

    uj5u.com 2023-04-20 08:28:06 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:27:27 more
  • 快取與資料庫雙寫一致性幾種策略分析

    本文將對幾種快取與資料庫保證資料一致性的使用方式進行分析。為保證高并發性能,以下分析場景不考慮執行的原子性及加鎖等強一致性要求的場景,僅追求最終一致性。 ......

    uj5u.com 2023-04-20 08:26:48 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:26:35 more
  • 云時代,MySQL到ClickHouse資料同步產品對比推薦

    ClickHouse 在執行分析查詢時的速度優勢很好的彌補了MySQL的不足,但是對于很多開發者和DBA來說,如何將MySQL穩定、高效、簡單的同步到 ClickHouse 卻很困難。本文對比了 NineData、MaterializeMySQL(ClickHouse自帶)、Bifrost 三款產品... ......

    uj5u.com 2023-04-20 08:26:29 more
  • sql陳述句優化

    問題查找及措施 問題查找 需要找到具體的代碼,對其進行一對一優化,而非一直把關注點放在服務器和sql平臺 降低簡化每個事務中處理的問題,盡量不要讓一個事務拖太長的時間 例如檔案上傳時,應將檔案上傳這一步放在事務外面 微軟建議 4.啟動sql定時執行計劃 怎么啟動sqlserver代理服務-百度經驗 ......

    uj5u.com 2023-04-20 08:25:13 more
  • Redis 報”OutOfDirectMemoryError“(堆外記憶體溢位)

    Redis 報錯“OutOfDirectMemoryError(堆外記憶體溢位) ”問題如下: 一、報錯資訊: 使用 Redis 的業務介面 ,產生 OutOfDirectMemoryError(堆外記憶體溢位),如圖: 格式化后的報錯資訊: { "timestamp": "2023-04-17 22: ......

    uj5u.com 2023-04-20 08:24:54 more
  • day02-2-商鋪查詢快取

    功能02-商鋪查詢快取 3.商鋪詳情快取查詢 3.1什么是快取? 快取就是資料交換的緩沖區(稱作Cache),是存盤資料的臨時地方,一般讀寫性能較高。 快取的作用: 降低后端負載 提高讀寫效率,降低回應時間 快取的成本: 資料一致性成本 代碼維護成本 運維成本 3.2需求說明 如下,當我們點擊商店詳 ......

    uj5u.com 2023-04-20 08:24:03 more
  • day02-短信登錄

    功能實作02 2.功能01-短信登錄 2.1基于Session實作登錄 2.1.1思路分析 2.1.2代碼實作 2.1.2.1發送短信驗證碼 發送短信驗證碼: 發送驗證碼的介面為:http://127.0.0.1:8080/api/user/code?phone=xxxxx<手機號> 請求方式:PO ......

    uj5u.com 2023-04-20 08:23:11 more