Is it possible to set default values for a DTO?

You can set default directly in your DTO class:

export class MyQuery {
  readonly myQueryItem = 'mydefault';
}

You have to instantiate the class so that the default value is used. For that you can for example use the ValidationPipe with the option transform: true. If the value is set by your query params it will be overriden.

@Get()
@UsePipes(new ValidationPipe({ transform: true }))
getHello(@Query() query: MyQuery) {
  return query;
}

Why does this work?

1) Pipes are applied to all your decorators, e.g. @Body(), @Param(), @Query() and can transform the values (e.g. ParseIntPipe) or perform checks (e.g. ValidationPipe).

2) The ValidationPipe internally uses class-validator and class-transformer for validation. To be able to perform validation on your input (plain javascript objects) it first has to transform them to your annotated dto class meaning it creates an instance of your class. With the setting transform: true it will automatically create an instance of your dto class.

Example (basically how it works):

class Person {
  firstname: string;
  lastname?: string = 'May';

  constructor(person) {
    Object.assign(this, person);
  }
}

// You can use Person as a type for a plain object -> no default value
const personInput: Person = { firstname: 'Yuna' };

// When an actual instance of the class is created, it uses the default value
const personInstance: Person = new Person(personInput);