Встановлення значення за замовчуванням для об'єкта TypeScript, переданого як аргумент


198
function sayName(params: {firstName: string; lastName?: string}) {
    params.lastName = params.lastName || 'smith';  // <<-- any better alternative to this?
    var name = params.firstName + params.lastName
    alert(name);
}

sayName({firstName: 'bob'});

Я уявляв, що щось подібне може спрацювати:

function sayName(params: {firstName: string; lastName: string = 'smith'}) {

Очевидно, що якщо це були прості аргументи, ви можете це зробити:

function sayName(firstName: string, lastName = 'smith') {
    var name = firstName + lastName;
    alert(name);
}

sayName('bob');

І в coffeescript у вас є доступ до оператора умовного існування, це може робити:

param.lastName ?= 'smith'

Який компілюється в javascript:

if (param.lastName == null) {
    param.lastName = 'smith';
}

Запропоноване рішення params.lastName = params.lastName || 'smith';насправді досить чудове - воно обробляє порожні рядки, невизначені рядки та нульові значення.
— Фентон

@SteveFenton І що-небудь хибне. Це добре у випадку з прізвищем, але, як правило, не гарна ідея. Ось чому Typescript переводить значення за замовчуванням у if(typeof x === "undefined") { … }. Не те, щоб ви цього не знали, а просто вказали на загальний випадок проведення ОП.
— Інго Бюрк

1
@ IngoBürk правда, але завдяки lastName?: stringцьому може бути колись так, як сказав СтівФентон, "обробляє порожні рядки, невизначені рядки та нульові значення".
— AJP

@AJP У Typescript, так. Але це лише час компіляції. Так чи інакше, як я вже сказав, лише вказавши на загальний сценарій :)
— Ingo Bürk,

2
Погодьтеся зі Стівом тут. Досить часто краще мати один конфігураційний аргумент, а не 10 аргументів. У цьому випадку params.lastName = params.lastName || 'smith';я використовую
— схему

Відповіді:


211

Насправді, мабуть, існує простий спосіб. У TypeScript 1.5 працює наступний код:

function sayName({ first, last = 'Smith' }: {first: string; last?: string }): void {
  const name = first + ' ' + last;
  console.log(name);
}

sayName({ first: 'Bob' });

Трюк полягає в тому, щоб спочатку в дужках помістити, які ключі ви хочете вибрати з об’єкта аргументу, з key=valueбудь-якими за замовчуванням. Дотримуйтесь цього з :декларацією типу та типу.

Це трохи інакше, ніж те, що ви намагалися зробити, тому що замість того, щоб бути неушкодженим params об'єктом, ви натомість маєте зменшені змінні.

Якщо ви хочете зробити не обов'язковим передавати будь-яку функцію, додайте а ?для всіх клавіш типу і додайте за замовчуванням ={}після оголошення типу:

function sayName({first='Bob',last='Smith'}: {first?: string; last?: string}={}){
    var name = first + " " + last;
    alert(name);
}

sayName();

Це рішення передбачає функцію інтегресного натяку на код / ​​інтелігенцію, оскільки вона показує параметри, повністю знищені. Я не сподівався б побачити цей стиль в об'єкті налаштувань, що має декілька параметрів, як у прикладі.
— WiredPrairie

3
Чи можливо також переписати це рішення, щоб замість цього використовувати інтерфейс / клас типу "sayNameSettings"?
— Стеф Хейенрат

4
Хоча це працює, деструкція аргументів таким чином ускладнює дотримання IMO.
— PW Kad

1
ви можете використовувати ключове слово "як" (на мою думку, це читабельніше), наприклад {first = 'Bob', last = 'Smith'} як рядок {first ?: останнє ?: string}, але в ідеалі вам слід створити інтерфейс для вирішення цих випадків ...
— Frohlich

1
Чи є спосіб передати об’єкт параметрів іншій функції?
— Ділантхепігуй

53

Тепер Typescript підтримує параметри за замовчуванням:

https://www.typescriptlang.org/docs/handbook/functions.html

Крім того, додавання значення за замовчуванням дозволяє опустити декларацію типу, оскільки з нього можна зробити висновок зі значення за замовчуванням:

function sayName(firstName: string, lastName = "Smith") {
  const name = firstName + ' ' + lastName;
  alert(name);
}

sayName('Bob');

22
Як це стосується питання ОП щодо значення за замовчуванням для об'єкта TypeScript, переданого як аргумент? Вам слід показати приклад з аргументом об’єкта.
— demisx

9
Це не так, але я знайшов це запитання, коли шукав, як взагалі задати параметри за замовчуванням у typecript, і жоден з відповідей не вирішив цього. Я також розмістив цю відповідь ще до того, як я помітив тонке «об’єктне» роз'яснення парам
— загравати

29

Об'єкт деструктуризації об'єкта параметрів - це те, до чого прагнуть багато відповідей, наведених вище, і в Typescript тепер є створені методи для полегшення читання та інтуїтивного розуміння.

Основи руйнування: Деструктуючи об'єкт, ви можете вибрати властивості об’єкта за ключовим іменем. Ви можете визначити як мало або скільки завдань, які вам подобаються, а значення за замовчуванням встановлюються базовим синтаксисом let {key = default} = object.

let {firstName, lastName = 'Smith'} = myParamsObject;

//Compiles to:
var firstName = myParamsObject.firstName, 
_a = myParamsObject.lastName, 
lastName = _a === void 0 ? 'Smith' : _a;

Запис інтерфейсу, типу або класу для об'єкта параметра покращує розбірливість.

type FullName = {
  firstName: string;
   
  /** @default 'Smith' */
  lastName ? : string;
}

function sayName(params: FullName) {

  // Set defaults for parameter object
  var { firstName, lastName = 'Smith'} = params;

  // Do Stuff
  var name = firstName + " " + lastName;
  alert(name);
}

// Use it
sayName({
  firstName: 'Bob'
});


3
Я думаю, що це найкраща відповідь на питання!
— Гезим

24

Ні, TypeScript не має природного способу встановлення значень за замовчуванням для властивостей об'єкта, визначених таким, як у одного, де за замовчуванням, а іншого немає. Ви можете визначити більш багату структуру:

class Name {
    constructor(public first : string, 
        public last: string = "Smith") {

    }
}

І використовувати це замість вбудованого визначення типу.

function sayName(name: Name) {
    alert(name.first + " " + name.last);
}

На жаль, ви не можете зробити щось подібне:

function sayName(name : { first: string; last?:string } 
       /* and then assign a default object matching the signature */  
       = { first: null, last: 'Smith' }) {

} 

Так як це було б встановлено за замовчуванням лише, якщо nameбуло undefined.


Я думаю, що це найкраща відповідь на це питання, і його слід позначити як правильну відповідь.
— капад

16

Це може бути приємним способом зробити це, що не передбачає довгих конструкторів

class Person {
    firstName?: string = 'Bob';
    lastName?: string = 'Smith';

    // Pass in this class as the required params
    constructor(params: Person) {
        // object.assign will overwrite defaults if params exist
        Object.assign(this, params)
    }
}

// you can still use the typing 
function sayName(params: Person){ 
    let name = params.firstName + params.lastName
    alert(name)
}

// you do have to call new but for my use case this felt better
sayName(new Person({firstName: 'Gordon'}))
sayName(new Person({lastName: 'Thomas'}))

2
@PWKad параметри за замовчуванням встановлені на другому та третьому рядку, "Bob" та "Smith"
— Cameron

3

Ось що можна спробувати, використовуючи інтерфейс та деструктуризацію зі значеннями за замовчуванням. Зверніть увагу, що "lastName" не є обов'язковим.

interface IName {
  firstName: string
  lastName?: string
}

function sayName(params: IName) {
  const { firstName, lastName = "Smith" } = params
  const fullName = `${firstName} ${lastName}`

  console.log("FullName-> ", fullName)
}

sayName({ firstName: "Bob" })

0

Не руйнуючись, ви можете створити параметри за замовчуванням і передати його

interface Name {
   firstName: string;
   lastName: string;
}

export const defaultName extends Omit<Name, 'firstName'> {
    lastName: 'Smith'
}

sayName({ ...defaultName, firstName: 'Bob' })
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.